Fri Aug 24 02:28:06 2007

Asterisk developer's documentation


res_jabber.c File Reference

A resource for interfacing asterisk directly as a client or a component to a jabber compliant server. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <iksemel.h>
#include "asterisk/channel.h"
#include "asterisk/jabber.h"
#include "asterisk/file.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/astobj.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"

Include dependency graph for res_jabber.c:

Go to the source code of this file.

Defines

#define FALSE   0
#define JABBER_CONFIG   "jabber.conf"
#define TRUE   1

Functions

static int aji_act_hook (void *data, int type, iks *node)
 The action hook parses the inbound packets, constantly running.
static void aji_buddy_destroy (struct aji_buddy *obj)
 Deletes the aji_buddy data structure.
static int aji_client_connect (void *data, ikspak *pak)
 connects as a client to jabber server.
static void aji_client_destroy (struct aji_client *obj)
 Deletes the aji_client data structure.
static int aji_client_info_handler (void *data, ikspak *pak)
static int aji_client_initialize (struct aji_client *client)
 prepares client for connect.
static int aji_component_initialize (struct aji_client *client)
 prepares component for connect.
static int aji_create_buddy (char *label, struct aji_client *client)
 creates transport. creates buddy.
static int aji_create_client (char *label, struct ast_variable *var, int debug)
 creates aji_client structure.
static int aji_dinfo_handler (void *data, ikspak *pak)
static int aji_ditems_handler (void *data, ikspak *pak)
static int aji_do_debug (int fd, int argc, char *argv[])
 turnon console debugging.
static int aji_do_reload (int fd, int argc, char *argv[])
 reload jabber module.
static int aji_filter_roster (void *data, ikspak *pak)
 filters the roster packet we get back from server.
static struct aji_resourceaji_find_resource (struct aji_buddy *buddy, char *name)
static struct aji_versionaji_find_version (char *node, char *version, ikspak *pak)
 Find version in XML stream and populate our capabilities list.
static int aji_get_roster (struct aji_client *client)
static void aji_handle_iq (struct aji_client *client, iks *node)
 Handles <iq> tags.
static void aji_handle_message (struct aji_client *client, ikspak *pak)
 Handles presence packets.
static void aji_handle_presence (struct aji_client *client, ikspak *pak)
static void aji_handle_subscribe (struct aji_client *client, ikspak *pak)
 handles subscription requests.
static int aji_highest_bit (int number)
 Detects the highest bit in a number.
static int aji_load_config (void)
 load config file.
static void aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming)
 the debug loop.
static int aji_no_debug (int fd, int argc, char *argv[])
 turnoff console debugging.
static void aji_pruneregister (struct aji_client *client)
 attempts to register to a transport. attempts to register to a transport step 2. goes through roster and prunes users not needed in list, or adds them accordingly.
static int aji_reconnect (struct aji_client *client)
static void * aji_recv_loop (void *data)
 receive message loop.
static int aji_register_approve_handler (void *data, ikspak *pak)
static int aji_register_query_handler (void *data, ikspak *pak)
static int aji_reload (void)
static int aji_send_exec (struct ast_channel *chan, void *data)
 Dial plan function to send a message.
static void aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc)
 set presence of client.
static int aji_show_clients (int fd, int argc, char *argv[])
 show client status.
static int aji_status_exec (struct ast_channel *chan, void *data)
 Dial plan function status(). puts the status of watched user into a channel variable.
static int aji_test (int fd, int argc, char *argv[])
 send test message for debugging.
int ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic)
 create a chatroom.
int ast_aji_disconnect (struct aji_client *client)
 disconnect from jabber server.
aji_clientast_aji_get_client (const char *name)
 grab a aji_client structure by label name.
aji_client_containerast_aji_get_clients (void)
void ast_aji_increment_mid (char *mid)
 increments the mid field for messages and other events.
int ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message)
 invite to a chatroom.
int ast_aji_join_chat (struct aji_client *client, char *room)
 join a chatroom.
int ast_aji_send (struct aji_client *client, const char *address, const char *message)
 sends messages.
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"AJI - Asterisk Jabber Interface",.load=load_module,.unload=unload_module,.reload=reload,)
static int gtalk_yuck (iks *node)
static iks * jabber_make_auth (iksid *id, const char *pass, const char *sid)
static int load_module (void)
static int manager_jabber_send (struct mansession *s, const struct message *m)
 Send a Jabber Message via call from the Manager.
static int reload (void)
static int unload_module (void)

Variables

static struct ast_cli_entry aji_cli []
static char * ajisend_descrip
static char * ajisend_synopsis = "JabberSend(jabber,screenname,message)"
static char * ajistatus_descrip
static char * ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)"
static char * app_ajisend = "JabberSend"
static char * app_ajistatus = "JabberStatus"
aji_capabilitiescapabilities = NULL
aji_client_container clients
static char debug_usage []
static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER }
 Global flags, initialized to default values.
static char mandescr_jabber_send []
static char no_debug_usage []
static char reload_usage []
static char test_usage []
static int tls_initialized = FALSE


Detailed Description

A resource for interfacing asterisk directly as a client or a component to a jabber compliant server.

Todo:
If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?
Todo:
If you have TLS, you can't unload this module. See bug #9738. This needs to be fixed, but the bug is in the unmantained Iksemel library

Definition in file res_jabber.c.


Define Documentation

#define FALSE   0

Definition at line 64 of file res_jabber.c.

#define JABBER_CONFIG   "jabber.conf"

Definition at line 61 of file res_jabber.c.

Referenced by aji_load_config().

#define TRUE   1

Definition at line 68 of file res_jabber.c.


Function Documentation

static int aji_act_hook ( void *  data,
int  type,
iks *  node 
) [static]

The action hook parses the inbound packets, constantly running.

Parameters:
data aji client structure
type type of packet
node the actual packet.
Returns:
IKS_OK or IKS_HOOK .

Definition at line 487 of file res_jabber.c.

References aji_client_connect(), aji_client_destroy(), AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, AJI_DISCONNECTING, aji_handle_iq(), aji_handle_message(), aji_handle_presence(), aji_handle_subscribe(), aji_highest_bit(), asprintf, ast_aji_increment_mid(), ast_base64encode(), ast_log(), ast_malloc, ast_sha1_hash(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::authorized, base64, aji_client::component, aji_client::f, free, jabber_make_auth(), aji_client::jid, len, LOG_DEBUG, LOG_ERROR, LOG_WARNING, aji_client::mid, option_debug, aji_client::p, aji_client::password, s, secret, aji_client::state, TRUE, aji_client::usesasl, and aji_client::usetls.

Referenced by aji_create_client().

00488 {
00489    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00490    ikspak *pak = NULL;
00491    iks *auth = NULL;
00492 
00493    if(!node) {
00494       ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */
00495       ASTOBJ_UNREF(client, aji_client_destroy);
00496       return IKS_HOOK;
00497    }
00498 
00499    if (client->state == AJI_DISCONNECTING) {
00500       ASTOBJ_UNREF(client, aji_client_destroy);
00501       return IKS_HOOK;
00502    }
00503 
00504    pak = iks_packet(node);
00505 
00506    if (!client->component) { /*client */
00507       switch (type) {
00508       case IKS_NODE_START:
00509          if (client->usetls && !iks_is_secure(client->p)) {
00510             if (iks_has_tls()) {
00511                iks_start_tls(client->p);
00512                tls_initialized = TRUE;
00513             } else
00514                ast_log(LOG_ERROR, "gnuTLS not installed. You need to recompile the Iksemel library with gnuTLS support\n");
00515             break;
00516          }
00517          if (!client->usesasl) {
00518             iks_filter_add_rule(client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, IKS_RULE_DONE);
00519             auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id"));
00520             if (auth) {
00521                iks_insert_attrib(auth, "id", client->mid);
00522                iks_insert_attrib(auth, "to", client->jid->server);
00523                ast_aji_increment_mid(client->mid);
00524                iks_send(client->p, auth);
00525                iks_delete(auth);
00526             } else
00527                ast_log(LOG_ERROR, "Out of memory.\n");
00528          }
00529          break;
00530 
00531       case IKS_NODE_NORMAL:
00532          {
00533             int features = 0;
00534             if (!strcmp("stream:features", iks_name(node))) {
00535                features = iks_stream_features(node);
00536                if (client->usesasl) {
00537                   if (client->usetls && !iks_is_secure(client->p))
00538                      break;
00539                   if (client->authorized) {
00540                      if (features & IKS_STREAM_BIND) {
00541                         iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
00542                         auth = iks_make_resource_bind(client->jid);
00543                         if (auth) {
00544                            iks_insert_attrib(auth, "id", client->mid);
00545                            ast_aji_increment_mid(client->mid);
00546                            iks_send(client->p, auth);
00547                            iks_delete(auth);
00548                         } else {
00549                            ast_log(LOG_ERROR, "Out of memory.\n");
00550                            break;
00551                         }
00552                      }
00553                      if (features & IKS_STREAM_SESSION) {
00554                         iks_filter_add_rule (client->f, aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "auth", IKS_RULE_DONE);
00555                         auth = iks_make_session();
00556                         if (auth) {
00557                            iks_insert_attrib(auth, "id", "auth");
00558                            ast_aji_increment_mid(client->mid);
00559                            iks_send(client->p, auth);
00560                            iks_delete(auth);
00561                         } else {
00562                            ast_log(LOG_ERROR, "Out of memory.\n");
00563                         }
00564                      }
00565                   } else {
00566                      if (!client->jid->user) {
00567                         ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full);
00568                         break;
00569                      }
00570                      features = aji_highest_bit(features);
00571                      if (features == IKS_STREAM_SASL_MD5)
00572                         iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password);
00573                      else {
00574                         if (features == IKS_STREAM_SASL_PLAIN) {
00575                            iks *x = NULL;
00576                            x = iks_new("auth");
00577                            if (x) {
00578                               int len = strlen(client->jid->user) + strlen(client->password) + 3;
00579                               /* XXX Check return values XXX */
00580                               char *s = ast_malloc(80 + len);
00581                               char *base64 = ast_malloc(80 + len * 2);
00582                               iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
00583                               iks_insert_attrib(x, "mechanism", "PLAIN");
00584                               sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password);
00585                               ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
00586                               iks_insert_cdata(x, base64, 0);
00587                               iks_send(client->p, x);
00588                               iks_delete(x);
00589                               if (base64)
00590                                  free(base64);
00591                               if (s)
00592                                  free(s);
00593                            } else {
00594                               ast_log(LOG_ERROR, "Out of memory.\n");
00595                            }
00596                         }
00597                      }
00598                   }
00599                }
00600             } else if (!strcmp("failure", iks_name(node))) {
00601                ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
00602             } else if (!strcmp("success", iks_name(node))) {
00603                client->authorized = 1;
00604                iks_send_header(client->p, client->jid->server);
00605             }
00606             break;
00607          }
00608       case IKS_NODE_ERROR: 
00609             ast_log(LOG_ERROR, "JABBER: Node Error\n");
00610             ASTOBJ_UNREF(client, aji_client_destroy);
00611             return IKS_HOOK;
00612             break;
00613       case IKS_NODE_STOP: 
00614             ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00615             ASTOBJ_UNREF(client, aji_client_destroy);
00616             return IKS_HOOK;
00617             break;
00618       }
00619    } else if (client->state != AJI_CONNECTED && client->component) {
00620       switch (type) {
00621       case IKS_NODE_START:
00622          if (client->state == AJI_DISCONNECTED) {
00623             char secret[160], shasum[320], *handshake;
00624 
00625             sprintf(secret, "%s%s", pak->id, client->password);
00626             ast_sha1_hash(shasum, secret);
00627             handshake = NULL;
00628             asprintf(&handshake, "<handshake>%s</handshake>", shasum);
00629             if (handshake) {
00630                iks_send_raw(client->p, handshake);
00631                free(handshake);
00632                handshake = NULL;
00633             }
00634             client->state = AJI_CONNECTING;
00635             if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
00636                client->state = AJI_CONNECTED;
00637             else
00638                ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
00639             break;
00640          }
00641          break;
00642 
00643       case IKS_NODE_NORMAL:
00644          break;
00645 
00646       case IKS_NODE_ERROR:
00647          ast_log(LOG_ERROR, "JABBER: Node Error\n");
00648          ASTOBJ_UNREF(client, aji_client_destroy);
00649          return IKS_HOOK;
00650 
00651       case IKS_NODE_STOP:
00652          ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00653          ASTOBJ_UNREF(client, aji_client_destroy);
00654          return IKS_HOOK;
00655       }
00656    }
00657 
00658    switch (pak->type) {
00659    case IKS_PAK_NONE:
00660       if (option_debug)
00661          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n");
00662       break;
00663    case IKS_PAK_MESSAGE:
00664       aji_handle_message(client, pak);
00665       if (option_debug)
00666          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n");
00667       break;
00668    case IKS_PAK_PRESENCE:
00669       aji_handle_presence(client, pak);
00670       if (option_debug)
00671          ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n");
00672       break;
00673    case IKS_PAK_S10N:
00674       aji_handle_subscribe(client, pak);
00675       if (option_debug)
00676          ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n");
00677       break;
00678    case IKS_PAK_IQ:
00679       if (option_debug)
00680          ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n");
00681       aji_handle_iq(client, node);
00682       break;
00683    default:
00684       if (option_debug)
00685          ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type);
00686       break;
00687    }
00688    
00689    iks_filter_packet(client->f, pak);
00690 
00691    if (node)
00692       iks_delete(node);
00693 
00694    ASTOBJ_UNREF(client, aji_client_destroy);
00695    return IKS_OK;
00696 }

static void aji_buddy_destroy ( struct aji_buddy obj  )  [static]

Deletes the aji_buddy data structure.

Parameters:
obj is the structure we will delete.
Returns:
void.

Definition at line 211 of file res_jabber.c.

References aji_resource::description, free, aji_resource::next, and aji_buddy::resources.

Referenced by aji_client_destroy(), aji_create_buddy(), and aji_handle_presence().

00212 {
00213    struct aji_resource *tmp;
00214 
00215    while ((tmp = obj->resources)) {
00216       obj->resources = obj->resources->next;
00217       free(tmp->description);
00218       free(tmp);
00219    }
00220 
00221    free(obj);
00222 }

static int aji_client_connect ( void *  data,
ikspak *  pak 
) [static]

connects as a client to jabber server.

Parameters:
aji_client struct, and xml packet.
Returns:
res.

Definition at line 1856 of file res_jabber.c.

References aji_client_destroy(), AJI_CONNECTING, AJI_DISCONNECTED, aji_filter_roster(), aji_get_roster(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::component, aji_client::f, aji_client::jid, LOG_ERROR, aji_client::stack, and aji_client::state.

Referenced by aji_act_hook().

01857 {
01858    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01859    int res = 0;
01860 
01861    if (client) {
01862       if (client->state == AJI_DISCONNECTED) {
01863          iks_filter_add_rule(client->f, aji_filter_roster, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "roster", IKS_RULE_DONE);
01864          client->state = AJI_CONNECTING;
01865          client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
01866          iks_filter_remove_hook(client->f, aji_client_connect);
01867          if(!client->component) /*client*/
01868             aji_get_roster(client);
01869       }
01870    } else
01871       ast_log(LOG_ERROR, "Out of memory.\n");
01872 
01873    ASTOBJ_UNREF(client, aji_client_destroy);
01874    return res;
01875 }

static void aji_client_destroy ( struct aji_client obj  )  [static]

Deletes the aji_client data structure.

Parameters:
obj is the structure we will delete.
Returns:
void.

Definition at line 187 of file res_jabber.c.

References aji_buddy_destroy(), AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, aji_client::buddies, aji_client::f, free, aji_message::from, aji_message::message, aji_client::p, and aji_client::stack.

Referenced by aji_act_hook(), aji_client_connect(), aji_client_info_handler(), aji_create_client(), aji_dinfo_handler(), aji_ditems_handler(), aji_log_hook(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), ast_aji_disconnect(), and unload_module().

00188 {
00189    struct aji_message *tmp;
00190    ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy);
00191    ASTOBJ_CONTAINER_DESTROY(&obj->buddies);
00192    iks_filter_delete(obj->f);
00193    iks_parser_delete(obj->p);
00194    iks_stack_delete(obj->stack);
00195    AST_LIST_LOCK(&obj->messages);
00196    while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) {
00197       if (tmp->from)
00198          free(tmp->from);
00199       if (tmp->message)
00200          free(tmp->message);
00201    }
00202    AST_LIST_HEAD_DESTROY(&obj->messages);
00203    free(obj);
00204 }

static int aji_client_info_handler ( void *  data,
ikspak *  pak 
) [static]

Definition at line 903 of file res_jabber.c.

References aji_client_destroy(), aji_find_resource(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, aji_resource::cap, aji_client::jid, aji_version::jingle, LOG_ERROR, LOG_NOTICE, aji_client::p, and aji_resource::resource.

Referenced by aji_create_client().

00904 {
00905    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00906    struct aji_resource *resource = NULL;
00907    struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00908 
00909    resource = aji_find_resource(buddy, pak->from->resource);
00910    if (pak->subtype == IKS_TYPE_RESULT) {
00911       if (!resource) {
00912          ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00913          ASTOBJ_UNREF(client, aji_client_destroy);
00914          return IKS_FILTER_EAT;
00915       }
00916       if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00917          resource->cap->jingle = 1;
00918       } else
00919          resource->cap->jingle = 0;
00920    } else if (pak->subtype == IKS_TYPE_GET) {
00921       iks *iq, *disco, *ident, *google, *query;
00922       iq = iks_new("iq");
00923       query = iks_new("query");
00924       ident = iks_new("identity");
00925       disco = iks_new("feature");
00926       google = iks_new("feature");
00927       if (iq && ident && disco && google) {
00928          iks_insert_attrib(iq, "from", client->jid->full);
00929          iks_insert_attrib(iq, "to", pak->from->full);
00930          iks_insert_attrib(iq, "type", "result");
00931          iks_insert_attrib(iq, "id", pak->id);
00932          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
00933          iks_insert_attrib(ident, "category", "client");
00934          iks_insert_attrib(ident, "type", "pc");
00935          iks_insert_attrib(ident, "name", "asterisk");
00936          iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
00937          iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
00938          iks_insert_node(iq, query);
00939          iks_insert_node(query, ident);
00940          iks_insert_node(query, google);
00941          iks_insert_node(query, disco);
00942          iks_send(client->p, iq);
00943       } else
00944          ast_log(LOG_ERROR, "Out of Memory.\n");
00945       if (iq)
00946          iks_delete(iq);
00947       if (query)
00948          iks_delete(query);
00949       if (ident)
00950          iks_delete(ident);
00951       if (google)
00952          iks_delete(google);
00953       if (disco)
00954          iks_delete(disco);
00955    } else if (pak->subtype == IKS_TYPE_ERROR) {
00956       ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full);
00957    }
00958    ASTOBJ_UNREF(client, aji_client_destroy);
00959    return IKS_FILTER_EAT;
00960 }

static int aji_client_initialize ( struct aji_client client  )  [static]

prepares client for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1882 of file res_jabber.c.

References ast_log(), connected, aji_client::jid, LOG_ERROR, aji_client::p, aji_client::port, S_OR, and aji_client::serverhost.

Referenced by aji_reconnect().

01883 {
01884    int connected = 0;
01885 
01886    connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server);
01887 
01888    if (connected == IKS_NET_NOCONN) {
01889       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01890       return IKS_HOOK;
01891    } else   if (connected == IKS_NET_NODNS) {
01892       ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01893       return IKS_HOOK;
01894    } else
01895       iks_recv(client->p, 30);
01896    return IKS_OK;
01897 }

static int aji_component_initialize ( struct aji_client client  )  [static]

prepares component for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1904 of file res_jabber.c.

References ast_log(), connected, aji_client::jid, LOG_ERROR, aji_client::p, aji_client::port, S_OR, aji_client::serverhost, and aji_client::user.

Referenced by aji_reconnect().

01905 {
01906    int connected = 1;
01907 
01908    connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->user);
01909    if (connected == IKS_NET_NOCONN) {
01910       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01911       return IKS_HOOK;
01912    } else if (connected == IKS_NET_NODNS) {
01913       ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01914       return IKS_HOOK;
01915    } else if (!connected) 
01916       iks_recv(client->p, 30);
01917    return IKS_OK;
01918 }

static int aji_create_buddy ( char *  label,
struct aji_client client 
) [static]

creates transport. creates buddy.

Parameters:
label,buddy to dump it into.
Returns:
0.

Definition at line 2295 of file res_jabber.c.

References aji_buddy_destroy(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_LINK, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, LOG_WARNING, and malloc.

Referenced by aji_create_client(), and aji_handle_presence().

02296 {
02297    struct aji_buddy *buddy = NULL;
02298    int flag = 0;
02299    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
02300    if (!buddy) {
02301       flag = 1;
02302       buddy = malloc(sizeof(struct aji_buddy));
02303       if(!buddy) {
02304          ast_log(LOG_WARNING, "Out of memory\n");
02305          return 0;
02306       }
02307       memset(buddy, 0, sizeof(struct aji_buddy));
02308       ASTOBJ_INIT(buddy);
02309    }
02310    ASTOBJ_WRLOCK(buddy);
02311    ast_copy_string(buddy->name, label, sizeof(buddy->name));
02312    ASTOBJ_UNLOCK(buddy);
02313    if(flag)
02314       ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
02315    else {
02316       ASTOBJ_UNMARK(buddy);
02317       ASTOBJ_UNREF(buddy, aji_buddy_destroy);
02318    }
02319    return 1;
02320 }

static int aji_create_client ( char *  label,
struct ast_variable var,
int  debug 
) [static]

creates aji_client structure.

Parameters:
label,ast_variable,debug,pruneregister,component/client,aji_client to dump into.
Returns:
0.

Definition at line 2104 of file res_jabber.c.

References aji_act_hook(), AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_destroy(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_copy_flags, ast_false(), AST_FLAGS_ALL, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::f, aji_client::forcessl, free, globalflags, aji_client::jid, aji_client::keepalive, LOG_ERROR, malloc, aji_client::message_timeout, aji_client::mid, aji_client::p, aji_client::password, aji_client::port, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and var.

Referenced by aji_load_config().

02105 {
02106    char *resource;
02107    struct aji_client *client = NULL;
02108    int flag = 0;
02109 
02110    client = ASTOBJ_CONTAINER_FIND(&clients,label);
02111    if (!client) {
02112       flag = 1;
02113       client = (struct aji_client *) malloc(sizeof(struct aji_client));
02114       if (!client) {
02115          ast_log(LOG_ERROR, "Out of memory!\n");
02116          return 0;
02117       }
02118       memset(client, 0, sizeof(struct aji_client));
02119       ASTOBJ_INIT(client);
02120       ASTOBJ_WRLOCK(client);
02121       ASTOBJ_CONTAINER_INIT(&client->buddies);
02122    } else {
02123       ASTOBJ_WRLOCK(client);
02124       ASTOBJ_UNMARK(client);
02125    }
02126    ASTOBJ_CONTAINER_MARKALL(&client->buddies);
02127    ast_copy_string(client->name, label, sizeof(client->name));
02128    ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
02129 
02130    /* Set default values for the client object */
02131    client->debug = debug;
02132    ast_copy_flags(client, &globalflags, AST_FLAGS_ALL);
02133    client->port = 5222;
02134    client->usetls = 1;
02135    client->usesasl = 1;
02136    client->forcessl = 0;
02137    client->keepalive = 1;
02138    client->timeout = 50;
02139    client->message_timeout = 100;
02140    AST_LIST_HEAD_INIT(&client->messages);
02141    client->component = 0;
02142    ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
02143 
02144    if (flag) {
02145       client->authorized = 0;
02146       client->state = AJI_DISCONNECTED;
02147    }
02148    while (var) {
02149       if (!strcasecmp(var->name, "username"))
02150          ast_copy_string(client->user, var->value, sizeof(client->user));
02151       else if (!strcasecmp(var->name, "serverhost"))
02152          ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost));
02153       else if (!strcasecmp(var->name, "secret"))
02154          ast_copy_string(client->password, var->value, sizeof(client->password));
02155       else if (!strcasecmp(var->name, "statusmessage"))
02156          ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage));
02157       else if (!strcasecmp(var->name, "port"))
02158          client->port = atoi(var->value);
02159       else if (!strcasecmp(var->name, "timeout"))
02160          client->message_timeout = atoi(var->value);
02161       else if (!strcasecmp(var->name, "debug"))
02162          client->debug = (ast_false(var->value)) ? 0 : 1;
02163       else if (!strcasecmp(var->name, "type")) {
02164          if (!strcasecmp(var->value, "component"))
02165             client->component = 1;
02166       } else if (!strcasecmp(var->name, "usetls")) {
02167          client->usetls = (ast_false(var->value)) ? 0 : 1;
02168       } else if (!strcasecmp(var->name, "usesasl")) {
02169          client->usesasl = (ast_false(var->value)) ? 0 : 1;
02170       } else if (!strcasecmp(var->name, "forceoldssl"))
02171          client->forcessl = (ast_false(var->value)) ? 0 : 1;
02172       else if (!strcasecmp(var->name, "keepalive"))
02173          client->keepalive = (ast_false(var->value)) ? 0 : 1;
02174       else if (!strcasecmp(var->name, "autoprune"))
02175          ast_set2_flag(client, ast_true(var->value), AJI_AUTOPRUNE);
02176       else if (!strcasecmp(var->name, "autoregister"))
02177          ast_set2_flag(client, ast_true(var->value), AJI_AUTOREGISTER);
02178       else if (!strcasecmp(var->name, "buddy"))
02179             aji_create_buddy(var->value, client);
02180    /* no transport support in this version */
02181    /* else if (!strcasecmp(var->name, "transport"))
02182             aji_create_transport(var->value, client);
02183    */
02184       var = var->next;
02185    }
02186    if (!flag) {
02187       ASTOBJ_UNLOCK(client);
02188       ASTOBJ_UNREF(client, aji_client_destroy);
02189       return 1;
02190    }
02191    client->p = iks_stream_new(((client->component) ? "jabber:component:accept" : "jabber:client"), client, aji_act_hook);
02192    if (!client->p) {
02193       ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name);
02194       return 0;
02195    }
02196    client->stack = iks_stack_new(8192, 8192);
02197    if (!client->stack) {
02198       ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name);
02199       return 0;
02200    }
02201    client->f = iks_filter_new();
02202    if (!client->f) {
02203       ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name);
02204       return 0;
02205    }
02206    if (!strchr(client->user, '/') && !client->component) { /*client */
02207       resource = NULL;
02208       asprintf(&resource, "%s/asterisk", client->user);
02209       if (resource) {
02210          client->jid = iks_id_new(client->stack, resource);
02211          free(resource);
02212       }
02213    } else
02214       client->jid = iks_id_new(client->stack, client->user);
02215    if (client->component) {
02216       iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
02217       iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
02218       iks_filter_add_rule(client->f, aji_register_query_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
02219       iks_filter_add_rule(client->f, aji_register_approve_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
02220    } else {
02221       iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
02222    }
02223    if (!strchr(client->user, '/') && !client->component) { /*client */
02224       resource = NULL;
02225       asprintf(&resource, "%s/asterisk", client->user);
02226       if (resource) {
02227          client->jid = iks_id_new(client->stack, resource);
02228          free(resource);
02229       }
02230    } else
02231       client->jid = iks_id_new(client->stack, client->user);
02232    iks_set_log_hook(client->p, aji_log_hook);
02233    ASTOBJ_UNLOCK(client);
02234    ASTOBJ_CONTAINER_LINK(&clients,client);
02235    return 1;
02236 }

static int aji_dinfo_handler ( void *  data,
ikspak *  pak 
) [static]

Definition at line 962 of file res_jabber.c.

References aji_client_destroy(), aji_find_resource(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, aji_resource::cap, commands, aji_version::jingle, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_client::p, aji_resource::resource, and aji_client::user.

Referenced by aji_create_client().

00963 {
00964    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00965    char *node = NULL;
00966    struct aji_resource *resource = NULL;
00967    struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00968 
00969    resource = aji_find_resource(buddy, pak->from->resource);
00970    if (pak->subtype == IKS_TYPE_ERROR) {
00971       ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n");
00972       return IKS_FILTER_EAT;
00973    }
00974    if (pak->subtype == IKS_TYPE_RESULT) {
00975       if (!resource) {
00976          ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00977          ASTOBJ_UNREF(client, aji_client_destroy);
00978          return IKS_FILTER_EAT;
00979       }
00980       if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00981          resource->cap->jingle = 1;
00982       } else
00983          resource->cap->jingle = 0;
00984    } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) {
00985       iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search;
00986 
00987       iq = iks_new("iq");
00988       query = iks_new("query");
00989       identity = iks_new("identity");
00990       disco = iks_new("feature");
00991       reg = iks_new("feature");
00992       commands = iks_new("feature");
00993       gateway = iks_new("feature");
00994       version = iks_new("feature");
00995       vcard = iks_new("feature");
00996       search = iks_new("feature");
00997 
00998       if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) {
00999          iks_insert_attrib(iq, "from", client->user);
01000          iks_insert_attrib(iq, "to", pak->from->full);
01001          iks_insert_attrib(iq, "id", pak->id);
01002          iks_insert_attrib(iq, "type", "result");
01003          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01004          iks_insert_attrib(identity, "category", "gateway");
01005          iks_insert_attrib(identity, "type", "pstn");
01006          iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX");
01007          iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco");
01008          iks_insert_attrib(reg, "var", "jabber:iq:register");
01009          iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
01010          iks_insert_attrib(gateway, "var", "jabber:iq:gateway");
01011          iks_insert_attrib(version, "var", "jabber:iq:version");
01012          iks_insert_attrib(vcard, "var", "vcard-temp");
01013          iks_insert_attrib(search, "var", "jabber:iq:search");
01014 
01015          iks_insert_node(iq, query);
01016          iks_insert_node(query, identity);
01017          iks_insert_node(query, disco);
01018          iks_insert_node(query, reg);
01019          iks_insert_node(query, commands);
01020          iks_insert_node(query, gateway);
01021          iks_insert_node(query, version);
01022          iks_insert_node(query, vcard);
01023          iks_insert_node(query, search);
01024          iks_send(client->p, iq);
01025       } else {
01026          ast_log(LOG_ERROR, "Out of memory.\n");
01027       }
01028 
01029       if (iq)
01030          iks_delete(iq);
01031       if (query)
01032          iks_delete(query);
01033       if (identity)
01034          iks_delete(identity);
01035       if (disco)
01036          iks_delete(disco);
01037       if (reg)
01038          iks_delete(reg);
01039       if (commands)
01040          iks_delete(commands);
01041       if (gateway)
01042          iks_delete(gateway);
01043       if (version)
01044          iks_delete(version);
01045       if (vcard)
01046          iks_delete(vcard);
01047       if (search)
01048          iks_delete(search);
01049 
01050    } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) {
01051       iks *iq, *query, *confirm;
01052       iq = iks_new("iq");
01053       query = iks_new("query");
01054       confirm = iks_new("item");
01055 
01056       if (iq && query && confirm && client) {
01057          iks_insert_attrib(iq, "from", client->user);
01058          iks_insert_attrib(iq, "to", pak->from->full);
01059          iks_insert_attrib(iq, "id", pak->id);
01060          iks_insert_attrib(iq, "type", "result");
01061          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
01062          iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
01063          iks_insert_attrib(confirm, "node", "confirmaccount");
01064          iks_insert_attrib(confirm, "name", "Confirm AIM account");
01065          iks_insert_attrib(confirm, "jid", client->user);
01066          iks_insert_node(iq, query);
01067          iks_insert_node(query, confirm);
01068          iks_send(client->p, iq);
01069       } else {
01070          ast_log(LOG_ERROR, "Out of memory.\n");
01071       }
01072       if (iq)
01073          iks_delete(iq);
01074       if (query)
01075          iks_delete(query);
01076       if (confirm)
01077          iks_delete(confirm);
01078 
01079    } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) {
01080       iks *iq, *query, *feature;
01081 
01082       iq = iks_new("iq");
01083       query = iks_new("query");
01084       feature = iks_new("feature");
01085 
01086       if (iq && query && feature && client) {
01087          iks_insert_attrib(iq, "from", client->user);
01088          iks_insert_attrib(iq, "to", pak->from->full);
01089          iks_insert_attrib(iq, "id", pak->id);
01090          iks_insert_attrib(iq, "type", "result");
01091          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01092          iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
01093          iks_insert_node(iq, query);
01094          iks_insert_node(query, feature);
01095          iks_send(client->p, iq);
01096       } else {
01097          ast_log(LOG_ERROR, "Out of memory.\n");
01098       }
01099       if (iq)
01100          iks_delete(iq);
01101       if (query)
01102          iks_delete(query);
01103       if (feature)
01104          iks_delete(feature);
01105    }
01106 
01107    ASTOBJ_UNREF(client, aji_client_destroy);
01108    return IKS_FILTER_EAT;
01109 }

static int aji_ditems_handler ( void *  data,
ikspak *  pak 
) [static]

Definition at line 807 of file res_jabber.c.

References aji_client_destroy(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, aji_client::p, and aji_client::user.

Referenced by aji_create_client().

00808 {
00809    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00810    char *node = NULL;
00811 
00812    if (!(node = iks_find_attrib(pak->query, "node"))) {
00813       iks *iq = NULL, *query = NULL, *item = NULL;
00814       iq = iks_new("iq");
00815       query = iks_new("query");
00816       item = iks_new("item");
00817 
00818       if (iq && query && item) {
00819          iks_insert_attrib(iq, "from", client->user);
00820          iks_insert_attrib(iq, "to", pak->from->full);
00821          iks_insert_attrib(iq, "id", pak->id);
00822          iks_insert_attrib(iq, "type", "result");
00823          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00824          iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
00825          iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands");
00826          iks_insert_attrib(item, "jid", client->user);
00827 
00828          iks_insert_node(iq, query);
00829          iks_insert_node(query, item);
00830          iks_send(client->p, iq);
00831       } else {
00832          ast_log(LOG_ERROR, "Out of memory.\n");
00833       }
00834       if (iq)
00835          iks_delete(iq);
00836       if (query)
00837          iks_delete(query);
00838       if (item)
00839          iks_delete(item);
00840 
00841    } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
00842       iks *iq, *query, *confirm;
00843       iq = iks_new("iq");
00844       query = iks_new("query");
00845       confirm = iks_new("item");
00846       if (iq && query && confirm && client) {
00847          iks_insert_attrib(iq, "from", client->user);
00848          iks_insert_attrib(iq, "to", pak->from->full);
00849          iks_insert_attrib(iq, "id", pak->id);
00850          iks_insert_attrib(iq, "type", "result");
00851          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00852          iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
00853          iks_insert_attrib(confirm, "node", "confirmaccount");
00854          iks_insert_attrib(confirm, "name", "Confirm AIM account");
00855          iks_insert_attrib(confirm, "jid", "blog.astjab.org");
00856 
00857          iks_insert_node(iq, query);
00858          iks_insert_node(query, confirm);
00859          iks_send(client->p, iq);
00860       } else {
00861          ast_log(LOG_ERROR, "Out of memory.\n");
00862       }
00863       if (iq)
00864          iks_delete(iq);
00865       if (query)
00866          iks_delete(query);
00867       if (confirm)
00868          iks_delete(confirm);
00869 
00870    } else if (!strcasecmp(node, "confirmaccount")) {
00871       iks *iq = NULL, *query = NULL, *feature = NULL;
00872 
00873       iq = iks_new("iq");
00874       query = iks_new("query");
00875       feature = iks_new("feature");
00876 
00877       if (iq && query && feature && client) {
00878          iks_insert_attrib(iq, "from", client->user);
00879          iks_insert_attrib(iq, "to", pak->from->full);
00880          iks_insert_attrib(iq, "id", pak->id);
00881          iks_insert_attrib(iq, "type", "result");
00882          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00883          iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
00884          iks_insert_node(iq, query);
00885          iks_insert_node(query, feature);
00886          iks_send(client->p, iq);
00887       } else {
00888          ast_log(LOG_ERROR, "Out of memory.\n");
00889       }
00890       if (iq)
00891          iks_delete(iq);
00892       if (query)
00893          iks_delete(query);
00894       if (feature)
00895          iks_delete(feature);
00896    }
00897 
00898    ASTOBJ_UNREF(client, aji_client_destroy);
00899    return IKS_FILTER_EAT;
00900 
00901 }

static int aji_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

turnon console debugging.

Parameters:
fd,number of args, args.
Returns:
RESULT_SUCCESS.

Definition at line 1975 of file res_jabber.c.

References ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, clients, and RESULT_SUCCESS.

01976 {
01977    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01978       ASTOBJ_RDLOCK(iterator); 
01979       iterator->debug = 1;
01980       ASTOBJ_UNLOCK(iterator);
01981    });
01982    ast_cli(fd, "Jabber Debugging Enabled.\n");
01983    return RESULT_SUCCESS;
01984 }

static int aji_do_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

reload jabber module.

Parameters:
fd,number of args, args.
Returns:
RESULT_SUCCESS.

Definition at line 1991 of file res_jabber.c.

References aji_reload(), ast_cli(), and RESULT_SUCCESS.

01992 {
01993    aji_reload();
01994    ast_cli(fd, "Jabber Reloaded.\n");
01995    return RESULT_SUCCESS;
01996 }

static int aji_filter_roster ( void *  data,
ikspak *  pak 
) [static]

filters the roster packet we get back from server.

Parameters:
aji_client struct, and xml packet.
Returns:
IKS_FILTER_EAT.

Definition at line 1745 of file res_jabber.c.

References AJI_AUTOPRUNE, AJI_AUTOREGISTER, AJI_CONNECTED, ast_clear_flag, ast_copy_flags, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_REF, ASTOBJ_UNLOCK, aji_client::buddies, and aji_client::state.

Referenced by aji_client_connect().

01746 {
01747    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01748    int flag = 0;
01749    iks *x = NULL;
01750    struct aji_buddy *buddy;
01751    
01752    client->state = AJI_CONNECTED;
01753    ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01754       ASTOBJ_RDLOCK(iterator);
01755       x = iks_child(pak->query);
01756       flag = 0;
01757       while (x) {
01758          if (!iks_strcmp(iks_name(x), "item")) {
01759             if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
01760                flag = 1;
01761                ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
01762             }
01763          }
01764          x = iks_next(x);
01765       }
01766       if (!flag)
01767          ast_copy_flags(iterator, client, AJI_AUTOREGISTER);
01768       if (x)
01769          iks_delete(x);
01770       ASTOBJ_UNLOCK(iterator);
01771    });
01772 
01773    x = iks_child(pak->query);
01774    while (x) {
01775       flag = 0;
01776       if (iks_strcmp(iks_name(x), "item") == 0) {
01777          ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01778             ASTOBJ_RDLOCK(iterator);
01779             if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
01780                flag = 1;
01781             ASTOBJ_UNLOCK(iterator);
01782          });
01783 
01784          if (!flag) {
01785             buddy = (struct aji_buddy *) malloc(sizeof(struct aji_buddy));
01786             if (!buddy) {
01787                ast_log(LOG_WARNING, "Out of memory\n");
01788                return 0;
01789             }
01790             memset(buddy, 0, sizeof(struct aji_buddy));
01791             ASTOBJ_INIT(buddy);
01792             ASTOBJ_WRLOCK(buddy);
01793             ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name));
01794             ast_clear_flag(buddy, AST_FLAGS_ALL);
01795             if(ast_test_flag(client, AJI_AUTOPRUNE)) {
01796                ast_set_flag(buddy, AJI_AUTOPRUNE);
01797                buddy->objflags |= ASTOBJ_FLAG_MARKED;
01798             } else
01799                ast_set_flag(buddy, AJI_AUTOREGISTER);
01800             ASTOBJ_UNLOCK(buddy);
01801             if (buddy) {
01802                ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
01803                ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01804             }
01805          }
01806       }
01807       x = iks_next(x);
01808    }
01809    if (x)
01810       iks_delete(x);
01811    aji_pruneregister(client);
01812 
01813    ASTOBJ_UNREF(client, aji_client_destroy);
01814    return IKS_FILTER_EAT;
01815 }

static struct aji_resource* aji_find_resource ( struct aji_buddy buddy,
char *  name 
) [static]

Definition at line 294 of file res_jabber.c.

References aji_resource::next, aji_resource::resource, and aji_buddy::resources.

Referenced by aji_client_info_handler(), aji_dinfo_handler(), and aji_status_exec().

00295 {
00296    struct aji_resource *res = NULL;
00297    if (!buddy || !name)
00298       return res;
00299    res = buddy->resources;
00300    while (res) {
00301       if (!strcasecmp(res->resource, name)) {
00302          break;
00303       }
00304       res = res->next;
00305    }
00306    return res;
00307 }

static struct aji_version* aji_find_version ( char *  node,
char *  version,
ikspak *  pak 
) [static]

Find version in XML stream and populate our capabilities list.

Parameters:
node the node attribute in the caps element we'll look for or add to our list
version the version attribute in the caps element we'll look for or add to our list
pak the XML stanza we're processing
Returns:
a pointer to the added or found aji_version structure

Definition at line 233 of file res_jabber.c.

References ast_log(), capabilities, aji_version::jingle, LOG_ERROR, malloc, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::parent, aji_version::version, and aji_capabilities::versions.

Referenced by aji_handle_presence().

00234 {
00235    struct aji_capabilities *list = NULL;
00236    struct aji_version *res = NULL;
00237 
00238    list = capabilities;
00239 
00240    if(!node)
00241       node = pak->from->full;
00242    if(!version)
00243       version = "none supplied.";
00244    while(list) {
00245       if(!strcasecmp(list->node, node)) {
00246          res = list->versions;
00247          while(res) {
00248              if(!strcasecmp(res->version, version))
00249                 return res;
00250              res = res->next;
00251          }
00252          /* Specified version not found. Let's add it to 
00253             this node in our capabilities list */
00254          if(!res) {
00255             res = (struct aji_version *)malloc(sizeof(struct aji_version));
00256             if(!res) {
00257                ast_log(LOG_ERROR, "Out of memory!\n");
00258                return NULL;
00259             }
00260             res->jingle = 0;
00261             res->parent = list;
00262             ast_copy_string(res->version, version, sizeof(res->version));
00263             res->next = list->versions;
00264             list->versions = res;
00265             return res;
00266          }
00267       }
00268       list = list->next;
00269    }
00270    /* Specified node not found. Let's add it our capabilities list */
00271    if(!list) {
00272       list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities));
00273       if(!list) {
00274          ast_log(LOG_ERROR, "Out of memory!\n");
00275          return NULL;
00276       }
00277       res = (struct aji_version *)malloc(sizeof(struct aji_version));
00278       if(!res) {
00279          ast_log(LOG_ERROR, "Out of memory!\n");
00280          return NULL;
00281       }
00282       ast_copy_string(list->node, node, sizeof(list->node));
00283       ast_copy_string(res->version, version, sizeof(res->version));
00284       res->jingle = 0;
00285       res->parent = list;
00286       res->next = NULL;
00287       list->versions = res;
00288       list->next = capabilities;
00289       capabilities = list;
00290    }
00291    return res;
00292 }

static int aji_get_roster ( struct aji_client client  )  [static]

Definition at line 1837 of file res_jabber.c.

References aji_set_presence(), aji_client::jid, aji_client::p, and aji_client::statusmessage.

Referenced by aji_client_connect(), and aji_reload().

01838 {
01839    iks *roster = NULL;
01840    roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
01841    if(roster) {
01842       iks_insert_attrib(roster, "id", "roster");
01843       aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
01844       iks_send(client->p, roster);
01845    }
01846    if (roster)
01847       iks_delete(roster);
01848    return 1;
01849 }

static void aji_handle_iq ( struct aji_client client,
iks *  node 
) [static]

Handles <iq> tags.

Parameters:
client structure and the iq node.
Returns:
void.

Definition at line 1116 of file res_jabber.c.

Referenced by aji_act_hook().

01117 {
01118    /*Nothing to see here */
01119 }

static void aji_handle_message ( struct aji_client client,
ikspak *  pak 
) [static]

Handles presence packets.

Parameters:
client structure and the node.
Returns:
void.

Definition at line 1126 of file res_jabber.c.

References aji_message::arrived, ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_strdup, free, aji_message::from, aji_message::id, aji_message::message, and aji_client::message_timeout.

Referenced by aji_act_hook().

01127 {
01128    struct aji_message *insert, *tmp;
01129    int flag = 0;
01130    
01131    if (!(insert = ast_calloc(1, sizeof(struct aji_message))))
01132       return;
01133    time(&insert->arrived);
01134    if (iks_find_cdata(pak->x, "body"))
01135       insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
01136    if(pak->id)
01137       ast_copy_string(insert->id, pak->id, sizeof(insert->message));
01138    if (pak->from)
01139       insert->from = ast_strdup(pak->from->full);
01140    AST_LIST_LOCK(&client->messages);
01141    AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
01142       if (flag) {
01143          AST_LIST_REMOVE_CURRENT(&client->messages, list);
01144          if (tmp->from)
01145             free(tmp->from);
01146          if (tmp->message)
01147             free(tmp->message);
01148       } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
01149          flag = 1;
01150          AST_LIST_REMOVE_CURRENT(&client->messages, list);
01151          if (tmp->from)
01152             free(tmp->from);
01153          if (tmp->message)
01154             free(tmp->message);
01155       }
01156    }
01157    AST_LIST_TRAVERSE_SAFE_END;
01158    AST_LIST_INSERT_HEAD(&client->messages, insert, list);
01159    AST_LIST_UNLOCK(&client->messages);
01160 }

static void aji_handle_presence ( struct aji_client client,
ikspak *  pak 
) [static]

Definition at line 1162 of file res_jabber.c.

References aji_buddy_destroy(), AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_increment_mid(), ast_log(), ast_strdup, ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, descrip, aji_resource::description, free, gtalk_yuck(), last, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, malloc, aji_client::mid, aji_resource::next, option_debug, option_verbose, aji_client::p, aji_resource::priority, aji_resource::resource, aji_buddy::resources, aji_client::state, aji_resource::status, aji_client::statusmessage, type, and VERBOSE_PREFIX_3.

Referenced by aji_act_hook().

01163 {
01164    int status, priority;
01165    struct aji_buddy *buddy;
01166    struct aji_resource *tmp = NULL, *last = NULL, *found = NULL;
01167    char *ver, *node, *descrip, *type;
01168    
01169    if(client->state != AJI_CONNECTED)
01170       aji_create_buddy(pak->from->partial, client);
01171 
01172    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
01173    if (!buddy) {
01174       ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial);
01175       return;
01176    }
01177    type = iks_find_attrib(pak->x, "type");
01178    if(client->component && type &&!strcasecmp("probe", type)) {
01179       aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01180       ast_verbose("what i was looking for \n");
01181    }
01182    ASTOBJ_WRLOCK(buddy);
01183    status = (pak->show) ? pak->show : 6;
01184    priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
01185    tmp = buddy->resources;
01186    descrip = ast_strdup(iks_find_cdata(pak->x,"status"));
01187 
01188    while (tmp) {
01189       if (!strcasecmp(tmp->resource, pak->from->resource)) {
01190          tmp->status = status;
01191          if (tmp->description) free(tmp->description);
01192          tmp->description = descrip;
01193          found = tmp;
01194          if (status == 6) {   /* Sign off Destroy resource */
01195             if (last && found->next) {
01196                last->next = found->next;
01197             } else if (!last) {
01198                if (found->next)
01199                   buddy->resources = found->next;
01200                else
01201                   buddy->resources = NULL;
01202             } else if (!found->next) {
01203                if (last)
01204                   last->next = NULL;
01205                else
01206                   buddy->resources = NULL;
01207             }
01208             free(found);
01209             found = NULL;
01210             break;
01211          }
01212          /* resource list is sorted by descending priority */
01213          if (tmp->priority != priority) {
01214             found->priority = priority;
01215             if (!last && !found->next)
01216                /* resource was found to be unique,
01217                   leave loop */
01218                break;
01219             /* search for resource in our list
01220                and take it out for the moment */
01221             if (last)
01222                last->next = found->next;
01223             else
01224                buddy->resources = found->next;
01225 
01226             last = NULL;
01227             tmp = buddy->resources;
01228             if (!buddy->resources)
01229                buddy->resources = found;
01230             /* priority processing */
01231             while (tmp) {
01232                /* insert resource back according to 
01233                   its priority value */
01234                if (found->priority > tmp->priority) {
01235                   if (last)
01236                      /* insert within list */
01237                      last->next = found;
01238                   found->next = tmp;
01239                   if (!last)
01240                      /* insert on top */
01241                      buddy->resources = found;
01242                   break;
01243                }
01244                if (!tmp->next) {
01245                   /* insert at the end of the list */
01246                   tmp->next = found;
01247                   found->next = NULL;
01248                   break;
01249                }
01250                last = tmp;
01251                tmp = tmp->next;
01252             }
01253          }
01254          break;
01255       }
01256       last = tmp;
01257       tmp = tmp->next;
01258    }
01259 
01260    /* resource not found in our list, create it */
01261    if (!found && status != 6) {
01262       found = (struct aji_resource *) malloc(sizeof(struct aji_resource));
01263       memset(found, 0, sizeof(struct aji_resource));
01264 
01265       if (!found) {
01266          ast_log(LOG_ERROR, "Out of memory!\n");
01267          return;
01268       }
01269       ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource));
01270       found->status = status;
01271       found->description = descrip;
01272       found->priority = priority;
01273       found->next = NULL;
01274       last = NULL;
01275       tmp = buddy->resources;
01276       while (tmp) {
01277          if (found->priority > tmp->priority) {
01278             if (last)
01279                last->next = found;
01280             found->next = tmp;
01281             if (!last)
01282                buddy->resources = found;
01283             break;
01284          }
01285          if (!tmp->next) {
01286             tmp->next = found;
01287             break;
01288          }
01289          last = tmp;
01290          tmp = tmp->next;
01291       }
01292       if (!tmp)
01293          buddy->resources = found;
01294    }
01295    
01296    /* if 'from' attribute does not contain 'resource' string
01297       point to the top of our resource list */
01298    if (!found && !pak->from->resource && buddy->resources) {
01299       found = buddy->resources;
01300    }
01301 
01302    ASTOBJ_UNLOCK(buddy);
01303    ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01304 
01305    node = iks_find_attrib(iks_find(pak->x, "c"), "node");
01306    ver = iks_find_attrib(iks_find(pak->x, "c"), "ver");
01307 
01308    /* handle gmail client's special caps:c tag */
01309    if (!node && !ver) {
01310       node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node");
01311       ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver");
01312    }
01313 
01314    if(status !=6 && !found->cap) {
01315       found->cap = aji_find_version(node, ver, pak);
01316       if(gtalk_yuck(pak->x)) /* gtalk should do discover */
01317          found->cap->jingle = 1;
01318       if(found->cap->jingle && option_debug > 4)
01319          ast_log(LOG_DEBUG,"Special case for google till they support discover.\n");
01320       else {
01321          iks *iq, *query;
01322          iq = iks_new("iq");
01323          query = iks_new("query");
01324          if(query && iq)  {
01325             iks_insert_attrib(iq, "type", "get");
01326             iks_insert_attrib(iq, "to", pak->from->full);
01327             iks_insert_attrib(iq,"from",iks_find_attrib(pak->x,"to"));
01328             iks_insert_attrib(iq, "id", client->mid);
01329             ast_aji_increment_mid(client->mid);
01330             iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01331             iks_insert_node(iq, query);
01332             iks_send(client->p, iq);
01333             
01334          } else
01335             ast_log(LOG_ERROR, "Out of memory.\n");
01336          if(query)
01337             iks_delete(query);
01338          if(iq)
01339             iks_delete(iq);
01340       }
01341    }
01342    if (option_verbose > 4) {
01343       switch (pak->subtype) {
01344       case IKS_TYPE_AVAILABLE:
01345          ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am available ^_* %i\n", pak->subtype);
01346          break;
01347       case IKS_TYPE_UNAVAILABLE:
01348          ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am unavailable ^_* %i\n", pak->subtype);
01349          break;
01350       default:
01351          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype);
01352       }
01353       switch (pak->show) {
01354       case IKS_SHOW_UNAVAILABLE:
01355          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01356          break;
01357       case IKS_SHOW_AVAILABLE:
01358          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is available\n");
01359          break;
01360       case IKS_SHOW_CHAT:
01361          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01362          break;
01363       case IKS_SHOW_AWAY:
01364          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is away\n");
01365          break;
01366       case IKS_SHOW_XA:
01367          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01368          break;
01369       case IKS_SHOW_DND:
01370          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01371          break;
01372       default:
01373          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Kinky! how did that happen %i\n", pak->show);
01374       }
01375    }
01376 }

static void aji_handle_subscribe ( struct aji_client client,
ikspak *  pak 
) [static]

handles subscription requests.

Parameters:
aji_client struct and xml packet.
Returns:
void.

Definition at line 1383 of file res_jabber.c.

References aji_set_presence(), ast_log(), ast_verbose(), aji_client::component, aji_client::jid, LOG_ERROR, option_verbose, aji_client::p, aji_resource::status, aji_client::statusmessage, and VERBOSE_PREFIX_3.

Referenced by aji_act_hook().

01384 {
01385    if(pak->subtype == IKS_TYPE_SUBSCRIBE) { 
01386       iks *presence = NULL, *status = NULL;
01387       presence = iks_new("presence");
01388       status = iks_new("status");
01389       if(presence && status) {
01390          iks_insert_attrib(presence, "type", "subscribed");
01391          iks_insert_attrib(presence, "to", pak->from->full);
01392          iks_insert_attrib(presence, "from", client->jid->full);
01393          if(pak->id)
01394             iks_insert_attrib(presence, "id", pak->id);
01395          iks_insert_cdata(status, "Asterisk has approved subscription", 0);
01396          iks_insert_node(presence, status);
01397          iks_send(client->p, presence);
01398       } else
01399          ast_log(LOG_ERROR, "Unable to allocate nodes\n");
01400       if(presence)
01401          iks_delete(presence);
01402       if(status)
01403          iks_delete(status);
01404       if(client->component)
01405          aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01406    }
01407    if (option_verbose > 4) {
01408       switch (pak->subtype) {
01409       case IKS_TYPE_SUBSCRIBE:
01410          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01411          break;
01412       case IKS_TYPE_SUBSCRIBED:
01413          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01414          break;
01415       case IKS_TYPE_UNSUBSCRIBE:
01416          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01417          break;
01418       case IKS_TYPE_UNSUBSCRIBED:
01419          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01420          break;
01421       default:          /*IKS_TYPE_ERROR: */
01422          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01423          break;
01424       }
01425    }
01426 }

static int aji_highest_bit ( int  number  )  [static]

Detects the highest bit in a number.

Parameters:
Number you want to have evaluated.
Returns:
the highest power of 2 that can go into the number.

Definition at line 321 of file res_jabber.c.

Referenced by aji_act_hook().

00322 {
00323    int x = sizeof(number) * 8 - 1;
00324    if (!number)
00325       return 0;
00326    for (; x > 0; x--) {
00327       if (number & (1 << x))
00328          break;
00329    }
00330    return (1 << x);
00331 }

static int aji_load_config ( void   )  [static]

load config file.

Parameters:
void. 
Returns:
1.

Definition at line 2327 of file res_jabber.c.

References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), ast_category_browse(), ast_config_load(), ast_false(), ast_log(), ast_set2_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), debug, globalflags, JABBER_CONFIG, LOG_WARNING, and var.

Referenced by aji_reload().

02328 {
02329    char *cat = NULL;
02330    int debug = 1;
02331    struct ast_config *cfg = NULL;
02332    struct ast_variable *var = NULL;
02333 
02334    cfg = ast_config_load(JABBER_CONFIG);
02335    if (!cfg) {
02336       ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
02337       return 0;
02338    }
02339 
02340    cat = ast_category_browse(cfg, NULL);
02341    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02342       if (!strcasecmp(var->name, "debug"))
02343          debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1;
02344       else if (!strcasecmp(var->name, "autoprune"))
02345          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE);
02346       else if (!strcasecmp(var->name, "autoregister"))
02347          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER);
02348    }
02349 
02350    while (cat) {
02351       if (strcasecmp(cat, "general")) {
02352             var = ast_variable_browse(cfg, cat);
02353             aji_create_client(cat, var, debug);
02354       }
02355       cat = ast_category_browse(cfg, cat);
02356    }
02357    return 1;
02358 }

static void aji_log_hook ( void *  data,
const char *  xmpp,
size_t  size,
int  is_incoming 
) [static]

the debug loop.

Parameters:
aji_client structure, xml data as string, size of string, direction of packet, 1 for inbound 0 for outbound.

Definition at line 460 of file res_jabber.c.

References aji_client_destroy(), ast_verbose(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::debug, EVENT_FLAG_USER, manager_event(), and option_debug.

Referenced by aji_create_client().

00461 {
00462    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00463    manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
00464 
00465    if (client->debug) {
00466       if (is_incoming)
00467          ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
00468       else {
00469          if( strlen(xmpp) == 1) {
00470             if(option_debug > 2  && xmpp[0] == ' ')
00471             ast_verbose("\nJABBER: Keep alive packet\n");
00472          } else
00473             ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
00474       }
00475 
00476    }
00477    ASTOBJ_UNREF(client, aji_client_destroy);
00478 }

static int aji_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

turnoff console debugging.

Parameters:
fd,number of args, args.
Returns:
RESULT_SUCCESS.

Definition at line 2003 of file res_jabber.c.

References ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, clients, and RESULT_SUCCESS.

02004 {
02005    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02006       ASTOBJ_RDLOCK(iterator);
02007       iterator->debug = 0;
02008       ASTOBJ_UNLOCK(iterator);
02009    });
02010    ast_cli(fd, "Jabber Debugging Disabled.\n");
02011    return RESULT_SUCCESS;
02012 }

static void aji_pruneregister ( struct aji_client client  )  [static]

attempts to register to a transport. attempts to register to a transport step 2. goes through roster and prunes users not needed in list, or adds them accordingly.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1692 of file res_jabber.c.

References AJI_AUTOPRUNE, AJI_AUTOREGISTER, ast_clear_flag, ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, aji_client::buddies, aji_client::jid, and aji_client::p.

01693 {
01694    int res = 0;
01695    iks *removeiq = iks_new("iq");
01696    iks *removequery = iks_new("query");
01697    iks *removeitem = iks_new("item");
01698    iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items");
01699 
01700    if (client && removeiq && removequery && removeitem && send) {
01701       iks_insert_node(removeiq, removequery);
01702       iks_insert_node(removequery, removeitem);
01703       ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01704          ASTOBJ_RDLOCK(iterator);
01705          /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never
01706           * be called at the same time */
01707          if (ast_test_flag(iterator, AJI_AUTOPRUNE)) {
01708             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
01709                   "GoodBye your status is no longer needed by Asterisk the Open Source PBX"
01710                   " so I am no longer subscribing to your presence.\n"));
01711             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
01712                   "GoodBye you are no longer in the asterisk config file so I am removing"
01713                   " your access to my presence.\n"));
01714             iks_insert_attrib(removeiq, "from", client->jid->full); 
01715             iks_insert_attrib(removeiq, "type", "set"); 
01716             iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster");
01717             iks_insert_attrib(removeitem, "jid", iterator->name);
01718             iks_insert_attrib(removeitem, "subscription", "remove");
01719             res = iks_send(client->p, removeiq);
01720          } else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) {
01721             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 
01722                   "Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
01723             ast_clear_flag(iterator, AJI_AUTOREGISTER);
01724          }
01725          ASTOBJ_UNLOCK(iterator);
01726       });
01727    } else
01728       ast_log(LOG_ERROR, "Out of memory.\n");
01729    if (removeiq)
01730       iks_delete(removeiq);
01731    if (removequery)
01732       iks_delete(removequery);
01733    if (removeitem)
01734       iks_delete(removeitem);
01735    if (send)
01736       iks_delete(send);
01737    ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy);
01738 }

static int aji_reconnect ( struct aji_client client  )  [static]

Definition at line 1817 of file res_jabber.c.

References aji_client_initialize(), aji_component_initialize(), AJI_DISCONNECTED, aji_client::authorized, aji_client::component, aji_client::p, aji_client::state, and aji_client::timeout.

Referenced by aji_recv_loop().

01818 {
01819    int res = 0;
01820 
01821    if (client->state)
01822       client->state = AJI_DISCONNECTED;
01823    client->timeout=50;
01824    if (client->p)
01825       iks_parser_reset(client->p);
01826    if (client->authorized)
01827       client->authorized = 0;
01828 
01829    if(client->component)
01830       res = aji_component_initialize(client);
01831    else
01832       res = aji_client_initialize(client);
01833 
01834    return res;
01835 }

static void * aji_recv_loop ( void *  data  )  [static]

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1541 of file res_jabber.c.

References aji_client_destroy(), AJI_CONNECTED, AJI_DISCONNECTING, aji_reconnect(), ast_log(), ast_verbose(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, aji_client::p, aji_client::state, and aji_client::timeout.

Referenced by aji_reload().

01542 {
01543    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01544    int res = IKS_HOOK;
01545    do {
01546       if (res != IKS_OK) {
01547          while(res != IKS_OK) {
01548             if(option_verbose > 3)
01549                ast_verbose("JABBER: reconnecting.\n");
01550             res = aji_reconnect(client);
01551             sleep(4);
01552          }
01553       }
01554 
01555       res = iks_recv(client->p, 1);
01556 
01557       if (client->state == AJI_DISCONNECTING) {
01558          if (option_debug > 1)
01559             ast_log(LOG_DEBUG, "Ending our Jabber client's thread due to a disconnect\n");
01560          pthread_exit(NULL);
01561       }
01562       client->timeout--;
01563       if (res == IKS_HOOK) 
01564          ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
01565       else if (res == IKS_NET_TLSFAIL)
01566          ast_log(LOG_WARNING, "JABBER:  Failure in TLS.\n");
01567       else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
01568          res = iks_send_raw(client->p, " ");
01569          if(res == IKS_OK)
01570             client->timeout = 50;
01571          else
01572             ast_log(LOG_WARNING, "JABBER:  Network Timeout\n");
01573       } else if (res == IKS_NET_RWERR)
01574          ast_log(LOG_WARNING, "JABBER: socket read error\n");
01575    } while (client);
01576    ASTOBJ_UNREF(client, aji_client_destroy);
01577    return 0;
01578 }

static int aji_register_approve_handler ( void *  data,
ikspak *  pak 
) [static]

Definition at line 698 of file res_jabber.c.

References aji_client_destroy(), ast_aji_increment_mid(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::jid, LOG_ERROR, aji_client::mid, and aji_client::p.

Referenced by aji_create_client().

00699 {
00700    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00701    iks *iq = NULL, *presence = NULL, *x = NULL;
00702 
00703    iq = iks_new("iq");
00704    presence = iks_new("presence");
00705    x = iks_new("x");
00706    if (client && iq && presence && x) {
00707       if (!iks_find(pak->query, "remove")) {
00708          iks_insert_attrib(iq, "from", client->jid->full);
00709          iks_insert_attrib(iq, "to", pak->from->full);
00710          iks_insert_attrib(iq, "id", pak->id);
00711          iks_insert_attrib(iq, "type", "result");
00712          iks_send(client->p, iq);
00713 
00714          iks_insert_attrib(presence, "from", client->jid->full);
00715          iks_insert_attrib(presence, "to", pak->from->partial);
00716          iks_insert_attrib(presence, "id", client->mid);
00717          ast_aji_increment_mid(client->mid);
00718          iks_insert_attrib(presence, "type", "subscribe");
00719          iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
00720          iks_insert_node(presence, x);
00721          iks_send(client->p, presence); 
00722       }
00723    } else {
00724       ast_log(LOG_ERROR, "Out of memory.\n");
00725    }
00726 
00727    if (iq)
00728       iks_delete(iq);
00729    if(presence)
00730       iks_delete(presence);
00731    if (x)
00732       iks_delete(x);
00733    ASTOBJ_UNREF(client, aji_client_destroy);
00734    return IKS_FILTER_EAT;
00735 }

static int aji_register_query_handler ( void *  data,
ikspak *  pak 
) [static]

Definition at line 737 of file res_jabber.c.

References aji_client_destroy(), ast_log(), ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, error(), LOG_ERROR, aji_client::p, and aji_client::user.

Referenced by aji_create_client().

00738 {
00739    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00740    struct aji_buddy *buddy = NULL; 
00741    char *node = NULL;
00742 
00743    client = (struct aji_client *) data;
00744 
00745    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00746    if (!buddy) {
00747       iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL;
00748       ast_verbose("Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
00749       iq = iks_new("iq");
00750       query = iks_new("query");
00751       error = iks_new("error");
00752       notacceptable = iks_new("not-acceptable");
00753       if(iq && query && error && notacceptable) {
00754          iks_insert_attrib(iq, "type", "error");
00755          iks_insert_attrib(iq, "from", client->user);
00756          iks_insert_attrib(iq, "to", pak->from->full);
00757          iks_insert_attrib(iq, "id", pak->id);
00758          iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00759          iks_insert_attrib(error, "code" , "406");
00760          iks_insert_attrib(error, "type", "modify");
00761          iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
00762          iks_insert_node(iq, query);
00763          iks_insert_node(iq, error);
00764          iks_insert_node(error, notacceptable);
00765          iks_send(client->p, iq);
00766       } else {
00767          ast_log(LOG_ERROR, "Out of memory.\n");
00768       }
00769       if (iq)
00770          iks_delete(iq);
00771       if (query)
00772          iks_delete(query);
00773       if (error)
00774          iks_delete(error);
00775       if (notacceptable)
00776          iks_delete(notacceptable);
00777    } else   if (!(node = iks_find_attrib(pak->query, "node"))) {
00778       iks *iq = NULL, *query = NULL, *instructions = NULL;
00779       char *explain = "Welcome to Asterisk - the Open Source PBX.\n";
00780       iq = iks_new("iq");
00781       query = iks_new("query");
00782       instructions = iks_new("instructions");
00783       if (iq && query && instructions && client) {
00784          iks_insert_attrib(iq, "from", client->user);
00785          iks_insert_attrib(iq, "to", pak->from->full);
00786          iks_insert_attrib(iq, "id", pak->id);
00787          iks_insert_attrib(iq, "type", "result");
00788          iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00789          iks_insert_cdata(instructions, explain, 0);
00790          iks_insert_node(iq, query);
00791          iks_insert_node(query, instructions);
00792          iks_send(client->p, iq);
00793       } else {
00794          ast_log(LOG_ERROR, "Out of memory.\n");
00795       }
00796       if (iq)
00797          iks_delete(iq);
00798       if (query)
00799          iks_delete(query);
00800       if (instructions)
00801          iks_delete(instructions);
00802    }
00803    ASTOBJ_UNREF(client, aji_client_destroy);
00804    return IKS_FILTER_EAT;
00805 }

static int aji_reload ( void   )  [static]

Definition at line 2429 of file res_jabber.c.

References aji_client_destroy(), AJI_CONNECTING, AJI_DISCONNECTED, aji_get_roster(), aji_load_config(), aji_recv_loop(), ast_log(), ast_pthread_create_background, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, clients, and LOG_ERROR.

Referenced by aji_do_reload(), load_module(), and reload().

02430 {
02431    ASTOBJ_CONTAINER_MARKALL(&clients);
02432    if (!aji_load_config()) {
02433       ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
02434       return 0;
02435    }
02436    ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
02437    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02438       ASTOBJ_RDLOCK(iterator);
02439       if(iterator->state == AJI_DISCONNECTED) {
02440          if (!iterator->thread)
02441             ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
02442       } else if (iterator->state == AJI_CONNECTING)
02443          aji_get_roster(iterator);
02444       ASTOBJ_UNLOCK(iterator);
02445    });
02446    
02447    return 1;
02448 }

static int aji_send_exec ( struct ast_channel chan,
void *  data 
) [static]

Dial plan function to send a message.

Parameters:
channel,and data, data is sender, reciever, message.
Returns:
0.

Definition at line 424 of file res_jabber.c.

References ast_aji_get_client(), ast_aji_send(), ast_log(), ast_strdupa, LOG_ERROR, LOG_WARNING, s, and strsep().

Referenced by load_module().

00425 {
00426    struct aji_client *client = NULL;
00427 
00428    char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL;
00429 
00430    if (!data) {
00431       ast_log(LOG_ERROR, "This application requires arguments.\n");
00432       return 0;
00433    }
00434    s = ast_strdupa(data);
00435    if (s) {
00436       sender = strsep(&s, "|");
00437       if (sender && (sender[0] != '\0')) {
00438          recipient = strsep(&s, "|");
00439          if (recipient && (recipient[0] != '\0')) {
00440             message = s;
00441          } else {
00442             ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data);
00443             return -1;
00444          }
00445       }
00446    }
00447    if (!(client = ast_aji_get_client(sender))) {
00448       ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00449       return -1;
00450    }
00451    if (strchr(recipient, '@') && message)
00452       ast_aji_send(client, recipient, message);
00453    return 0;
00454 }

static void aji_set_presence ( struct aji_client client,
char *  to,
char *  from,
int  level,
char *  desc 
) [static]

set presence of client.

Parameters:
aji_client struct, user to send it to, and from, level, description.
Returns:
void.

Definition at line 1943 of file res_jabber.c.

References ast_log(), LOG_ERROR, and aji_client::p.

Referenced by aji_get_roster(), aji_handle_presence(), and aji_handle_subscribe().

01944 {
01945    int res = 0;
01946    iks *presence = iks_make_pres(level, desc);
01947    iks *cnode = iks_new("c");
01948    iks *priority = iks_new("priority");
01949 
01950    iks_insert_cdata(priority, "0", 1);
01951    if (presence && cnode && client) {
01952       if(to)
01953          iks_insert_attrib(presence, "to", to);
01954       if(from)
01955          iks_insert_attrib(presence, "from", from);
01956       iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
01957       iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
01958       iks_insert_attrib(cnode, "ext", "voice-v1");
01959       iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
01960       iks_insert_node(presence, cnode);
01961       res = iks_send(client->p, presence);
01962    } else
01963       ast_log(LOG_ERROR, "Out of memory.\n");
01964    if (cnode)
01965       iks_delete(cnode);
01966    if (presence)
01967       iks_delete(presence);
01968 }

static int aji_show_clients ( int  fd,
int  argc,
char *  argv[] 
) [static]

show client status.

Parameters:
fd,number of args, args.
Returns:
RESULT_SUCCESS.

Definition at line 2019 of file res_jabber.c.

References AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and clients.

02020 {
02021    char *status;
02022    int count = 0;
02023    ast_cli(fd, "Jabber Users and their status:\n");
02024    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02025       ASTOBJ_RDLOCK(iterator);
02026       count++;
02027       switch (iterator->state) {
02028       case AJI_DISCONNECTED:
02029          status = "Disconnected";
02030          break;
02031       case AJI_CONNECTING:
02032          status = "Connecting";
02033          break;
02034       case AJI_CONNECTED:
02035          status = "Connected";
02036          break;
02037       default:
02038          status = "Unknown";
02039       }
02040       ast_cli(fd, "       User: %s     - %s\n", iterator->user, status);
02041       ASTOBJ_UNLOCK(iterator);
02042    });
02043    ast_cli(fd, "----\n");
02044    ast_cli(fd, "   Number of users: %d\n", count);
02045    return RESULT_SUCCESS;
02046 }

static int aji_status_exec ( struct ast_channel chan,
void *  data 
) [static]

Dial plan function status(). puts the status of watched user into a channel variable.

Parameters:
channel,and username,watched user, status var
Returns:
0.

Definition at line 360 of file res_jabber.c.

References aji_find_resource(), ast_aji_get_client(), ast_log(), ast_strdupa, ASTOBJ_CONTAINER_FIND, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), aji_resource::resource, aji_buddy::resources, s, aji_resource::status, and strsep().

Referenced by load_module().

00361 {
00362    struct aji_client *client = NULL;
00363    struct aji_buddy *buddy = NULL;
00364    struct aji_resource *r = NULL;
00365    char *s = NULL, *sender = NULL, *jid = NULL, *screenname = NULL, *resource = NULL, *variable = NULL;
00366    int stat = 7;
00367    char status[2];
00368 
00369    if (!data) {
00370       ast_log(LOG_ERROR, "This application requires arguments.\n");
00371       return 0;
00372    }
00373    s = ast_strdupa(data);
00374    if (s) {
00375       sender = strsep(&s, "|");
00376       if (sender && (sender[0] != '\0')) {
00377          jid = strsep(&s, "|");
00378          if (jid && (jid[0] != '\0')) {
00379             variable = s;
00380          } else {
00381             ast_log(LOG_ERROR, "Bad arguments\n");
00382             return -1;
00383          }
00384       }
00385    }
00386 
00387    if(!strchr(jid, '/')) {
00388       resource = NULL;
00389    } else {
00390       screenname = strsep(&jid, "/");
00391       resource = jid;
00392    }
00393    client = ast_aji_get_client(sender);
00394    if (!client) {
00395       ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00396       return -1;
00397    }
00398    if(!&client->buddies) {
00399       ast_log(LOG_WARNING, "No buddies for connection : %s\n", sender);
00400       return -1;
00401    }
00402    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, resource ? screenname: jid);
00403    if (!buddy) {
00404       ast_log(LOG_WARNING, "Could not find buddy in list : %s\n", resource ? screenname : jid);
00405       return -1;
00406    }
00407    r = aji_find_resource(buddy, resource);
00408    if(!r && buddy->resources) 
00409       r = buddy->resources;
00410    if(!r)
00411       ast_log(LOG_NOTICE, "Resource %s of buddy %s not found \n", resource, screenname);
00412    else
00413       stat = r->status;
00414    sprintf(status, "%d", stat);
00415    pbx_builtin_setvar_helper(chan, variable, status);
00416    return 0;
00417 }

static int aji_test ( int  fd,
int  argc,
char *  argv[] 
) [static]

send test message for debugging.

Parameters:
fd,number of args, args.
Returns:
RESULT_SUCCESS.

Definition at line 2053 of file res_jabber.c.

References ast_aji_send(), ast_cli(), ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, aji_client::buddies, aji_resource::cap, clients, aji_resource::description, aji_version::jingle, name, aji_resource::next, aji_capabilities::node, aji_version::parent, aji_resource::priority, aji_resource::resource, RESULT_FAILURE, RESULT_SHOWUSAGE, S_OR, aji_resource::status, and aji_version::version.

02054 {
02055    struct aji_client *client;
02056    struct aji_resource *resource;
02057    const char *name = "asterisk";
02058    struct aji_message *tmp;
02059 
02060    if (argc > 3)
02061       return RESULT_SHOWUSAGE;
02062    else if (argc == 3)
02063       name = argv[2];
02064 
02065    if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
02066       ast_cli(fd, "Unable to find client '%s'!\n", name);
02067       return RESULT_FAILURE;
02068    }
02069 
02070    /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */
02071    ast_aji_send(client, "mogorman@astjab.org", "blahblah");
02072    ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02073       ASTOBJ_RDLOCK(iterator);
02074       ast_verbose("User: %s\n", iterator->name);
02075       for (resource = iterator->resources; resource; resource = resource->next) {
02076          ast_verbose("Resource: %s\n", resource->resource);
02077          if(resource->cap) {
02078             ast_verbose("   client: %s\n", resource->cap->parent->node);
02079             ast_verbose("   version: %s\n", resource->cap->version);
02080             ast_verbose("   Jingle Capable: %d\n", resource->cap->jingle);
02081          }
02082          ast_verbose("  Priority: %d\n", resource->priority);
02083          ast_verbose("  Status: %d\n", resource->status); 
02084          ast_verbose("  Message: %s\n", S_OR(resource->description,"")); 
02085       }
02086       ASTOBJ_UNLOCK(iterator);
02087    });
02088    ast_verbose("\nOooh a working message stack!\n");
02089    AST_LIST_LOCK(&client->messages);
02090    AST_LIST_TRAVERSE(&client->messages, tmp, list) {
02091       ast_verbose("  Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, ""));
02092    }
02093    AST_LIST_UNLOCK(&client->messages);
02094    ASTOBJ_UNREF(client, aji_client_destroy);
02095 
02096    return RESULT_SUCCESS;
02097 }

int ast_aji_create_chat ( struct aji_client client,
char *  room,
char *  server,
char *  topic 
)

create a chatroom.

Parameters:
aji_client struct , room, server, topic for the room.
Returns:
0.

Definition at line 1457 of file res_jabber.c.

References ast_aji_increment_mid(), ast_log(), LOG_ERROR, aji_client::mid, and aji_client::p.

01458 {
01459    int res = 0;
01460    iks *iq = NULL;
01461    iq = iks_new("iq");
01462    if (iq && client) {
01463       iks_insert_attrib(iq, "type", "get");
01464       iks_insert_attrib(iq, "to", server);
01465       iks_insert_attrib(iq, "id", client->mid);
01466       ast_aji_increment_mid(client->mid);
01467       iks_send(client->p, iq);
01468    } else 
01469       ast_log(LOG_ERROR, "Out of memory.\n");
01470    return res;
01471 }

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1925 of file res_jabber.c.

References aji_client_destroy(), ast_verbose(), ASTOBJ_UNREF, option_verbose, aji_client::p, and VERBOSE_PREFIX_3.

Referenced by unload_module().

01926 {
01927    if (client) {
01928       if (option_verbose > 3)
01929          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n");
01930       iks_disconnect(client->p);
01931       iks_parser_delete(client->p);
01932       ASTOBJ_UNREF(client, aji_client_destroy);
01933    }
01934 
01935    return 1;
01936 }

struct aji_client* ast_aji_get_client ( const char *  name  ) 

grab a aji_client structure by label name.

Parameters:
void. 
Returns:
1.

Definition at line 2365 of file res_jabber.c.

References ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, clients, and aji_client::user.

Referenced by aji_send_exec(), aji_status_exec(), gtalk_create_member(), and manager_jabber_send().

02366 {
02367    struct aji_client *client = NULL;
02368 
02369    client = ASTOBJ_CONTAINER_FIND(&clients, name);
02370    if (!client && !strchr(name, '@'))
02371       client = ASTOBJ_CONTAINER_FIND_FULL(&clients, name, user,,, strcasecmp);
02372    return client;
02373 }

struct aji_client_container* ast_aji_get_clients ( void   ) 

Definition at line 2375 of file res_jabber.c.

References clients.

02376 {
02377    return &clients;
02378 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

Definition at line 1585 of file res_jabber.c.

Referenced by aji_act_hook(), aji_handle_presence(), aji_register_approve_handler(), ast_aji_create_chat(), ast_aji_invite_chat(), gtalk_action(), gtalk_create_candidates(), gtalk_digit(), gtalk_invite(), and gtalk_invite_response().

01586 {
01587    int i = 0;
01588 
01589    for (i = strlen(mid) - 1; i >= 0; i--) {
01590       if (mid[i] != 'z') {
01591          mid[i] = mid[i] + 1;
01592          i = 0;
01593       } else
01594          mid[i] = 'a';
01595    }
01596 }

int ast_aji_invite_chat ( struct aji_client client,
char *  user,
char *  room,
char *  message 
)

invite to a chatroom.

Parameters:
aji_client struct ,user, room, message.
Returns:
res.

Definition at line 1506 of file res_jabber.c.

References ast_aji_increment_mid(), ast_log(), LOG_ERROR, aji_client::mid, and aji_client::p.

01507 {
01508    int res = 0;
01509    iks *invite, *body, *namespace;
01510 
01511    invite = iks_new("message");
01512    body = iks_new("body");
01513    namespace = iks_new("x");
01514    if (client && invite && body && namespace) {
01515       iks_insert_attrib(invite, "to", user);
01516       iks_insert_attrib(invite, "id", client->mid);
01517       ast_aji_increment_mid(client->mid);
01518       iks_insert_cdata(body, message, 0);
01519       iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
01520       iks_insert_attrib(namespace, "jid", room);
01521       iks_insert_node(invite, body);
01522       iks_insert_node(invite, namespace);
01523       res = iks_send(client->p, invite);
01524    } else 
01525       ast_log(LOG_ERROR, "Out of memory.\n");
01526    if (body)
01527       iks_delete(body);
01528    if (namespace)
01529       iks_delete(namespace);
01530    if (invite)
01531       iks_delete(invite);
01532    return res;
01533 }

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1478 of file res_jabber.c.

References ast_log(), LOG_ERROR, aji_client::p, and aji_resource::priority.

01479 {
01480    int res = 0;
01481    iks *presence = NULL, *priority = NULL;
01482    presence = iks_new("presence");
01483    priority = iks_new("priority");
01484    if (presence && priority && client) {
01485       iks_insert_cdata(priority, "0", 1);
01486       iks_insert_attrib(presence, "to", room);
01487       iks_insert_node(presence, priority);
01488       res = iks_send(client->p, presence);
01489       iks_insert_cdata(priority, "5", 1);
01490       iks_insert_attrib(presence, "to", room);
01491       res = iks_send(client->p, presence);
01492    } else 
01493       ast_log(LOG_ERROR, "Out of memory.\n");
01494    if (presence)
01495       iks_delete(presence);
01496    if (priority)
01497       iks_delete(priority);
01498    return res;
01499 }

int ast_aji_send ( struct aji_client client,
const char *  address,
const char *  message 
)

sends messages.

Parameters:
aji_client struct , reciever, message.
Returns:
1.

Definition at line 1433 of file res_jabber.c.

References AJI_CONNECTED, ast_log(), aji_client::jid, LOG_ERROR, LOG_WARNING, aji_client::p, and aji_client::state.

Referenced by aji_send_exec(), aji_test(), and manager_jabber_send().

01434 {
01435    int res = 0;
01436    iks *message_packet = NULL;
01437    if (client->state == AJI_CONNECTED) {
01438       message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message);
01439       if (message_packet) {
01440          iks_insert_attrib(message_packet, "from", client->jid->full);
01441          res = iks_send(client->p, message_packet);
01442       } else {
01443          ast_log(LOG_ERROR, "Out of memory.\n");
01444       }
01445       if (message_packet)
01446          iks_delete(message_packet);
01447    } else
01448       ast_log(LOG_WARNING, "JABBER: Not connected can't send\n");
01449    return 1;
01450 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_GLOBAL_SYMBOLS  ,
"AJI - Asterisk Jabber Interface"  ,
load = load_module,
unload = unload_module,
reload = reload 
)

static int gtalk_yuck ( iks *  node  )  [static]

Definition at line 309 of file res_jabber.c.

Referenced by aji_handle_presence().

00310 {
00311    if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps"))
00312       return 1;
00313    return 0;
00314 }

static iks * jabber_make_auth ( iksid *  id,
const char *  pass,
const char *  sid 
) [static]

Definition at line 333 of file res_jabber.c.

References ast_sha1_hash().

Referenced by aji_act_hook().

00334 {
00335    iks *x, *y;
00336    x = iks_new("iq");
00337    iks_insert_attrib(x, "type", "set");
00338    y = iks_insert(x, "query");
00339    iks_insert_attrib(y, "xmlns", IKS_NS_AUTH);
00340    iks_insert_cdata(iks_insert(y, "username"), id->user, 0);
00341    iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0);
00342    if (sid) {
00343       char buf[41];
00344       char sidpass[100];
00345       snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass);
00346       ast_sha1_hash(buf, sidpass);
00347       iks_insert_cdata(iks_insert(y, "digest"), buf, 0);
00348    } else {
00349       iks_insert_cdata(iks_insert(y, "password"), pass, 0);
00350    }
00351    return x;
00352 }

static int load_module ( void   )  [static]

Definition at line 2483 of file res_jabber.c.

References aji_cli, aji_reload(), aji_send_exec(), aji_status_exec(), ast_cli_register_multiple(), ast_manager_register2(), AST_MODULE_LOAD_DECLINE, ast_register_application(), ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, manager_jabber_send(), and mandescr_jabber_send.

static int manager_jabber_send ( struct mansession s,
const struct message m 
) [static]

Send a Jabber Message via call from the Manager.

Definition at line 2388 of file res_jabber.c.

References ast_aji_get_client(), ast_aji_send(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), and s.

Referenced by load_module().

02389 {
02390    struct aji_client *client = NULL;
02391    const char *id = astman_get_header(m,"ActionID");
02392    const char *jabber = astman_get_header(m,"Jabber");
02393    const char *screenname = astman_get_header(m,"ScreenName");
02394    const char *message = astman_get_header(m,"Message");
02395 
02396    if (ast_strlen_zero(jabber)) {
02397       astman_send_error(s, m, "No transport specified");
02398       return 0;
02399    }
02400    if (ast_strlen_zero(screenname)) {
02401       astman_send_error(s, m, "No ScreenName specified");
02402       return 0;
02403    }
02404    if (ast_strlen_zero(message)) {
02405       astman_send_error(s, m, "No Message specified");
02406       return 0;
02407    }
02408 
02409    astman_send_ack(s, m, "Attempting to send Jabber Message");
02410    client = ast_aji_get_client(jabber);
02411    if (!client) {
02412       astman_send_error(s, m, "Could not find Sender");
02413       return 0;
02414    }  
02415    if (strchr(screenname, '@') && message){
02416       ast_aji_send(client, screenname, message);   
02417       if (!ast_strlen_zero(id))
02418          astman_append(s, "ActionID: %s\r\n",id);
02419       astman_append(s, "Response: Success\r\n");
02420       return 0;
02421    }
02422    if (!ast_strlen_zero(id))
02423       astman_append(s, "ActionID: %s\r\n",id);
02424    astman_append(s, "Response: Failure\r\n");
02425    return 0;
02426 }

static int reload ( void   )  [static]

Definition at line 2497 of file res_jabber.c.

References aji_reload().

02498 {
02499    aji_reload();
02500    return 0;
02501 }

static int unload_module ( void   )  [static]

Definition at line 2450 of file res_jabber.c.

References aji_cli, aji_client_destroy(), AJI_DISCONNECTING, ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_log(), ast_manager_unregister(), ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, clients, LOG_DEBUG, LOG_ERROR, and option_debug.

02451 {
02452 
02453    /* Check if TLS is initialized. If that's the case, we can't unload this
02454       module due to a bug in the iksemel library that will cause a crash or
02455       a deadlock. We're trying to find a way to handle this, but in the meantime
02456       we will simply refuse to die... 
02457     */
02458    if (tls_initialized) {
02459       ast_log(LOG_ERROR, "Module can't be unloaded due to a bug in the Iksemel library when using TLS.\n");
02460       return 1;   /* You need a forced unload to get rid of this module */
02461    }
02462 
02463    ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02464    ast_unregister_application(app_ajisend);
02465    ast_unregister_application(app_ajistatus);
02466    ast_manager_unregister("JabberSend");
02467    
02468    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02469       ASTOBJ_RDLOCK(iterator);
02470       if (option_debug > 2)
02471          ast_log(LOG_DEBUG, "JABBER: Releasing and disconneing client: %s\n", iterator->name);
02472       iterator->state = AJI_DISCONNECTING;
02473       ast_aji_disconnect(iterator);
02474       pthread_join(iterator->thread, NULL);
02475       ASTOBJ_UNLOCK(iterator);
02476    });
02477 
02478    ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy);
02479    ASTOBJ_CONTAINER_DESTROY(&clients);
02480    return 0;
02481 }


Variable Documentation

struct ast_cli_entry aji_cli[] [static]

Definition at line 131 of file res_jabber.c.

Referenced by load_module(), and unload_module().

char* ajisend_descrip [static]

Initial value:

"JabberSend(Jabber,ScreenName,Message)\n"
"  Jabber - Client or transport Asterisk uses to connect to Jabber\n" 
"  ScreenName - User Name to message.\n" 
"  Message - Message to be sent to the buddy\n"

Definition at line 157 of file res_jabber.c.

char* ajisend_synopsis = "JabberSend(jabber,screenname,message)" [static]

Definition at line 155 of file res_jabber.c.

char* ajistatus_descrip [static]

Definition at line 167 of file res_jabber.c.

char* ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)" [static]

Definition at line 165 of file res_jabber.c.

char* app_ajisend = "JabberSend" [static]

Definition at line 153 of file res_jabber.c.

char* app_ajistatus = "JabberStatus" [static]

Definition at line 163 of file res_jabber.c.

struct aji_capabilities* capabilities = NULL

Definition at line 176 of file res_jabber.c.

Referenced by aji_find_version(), and ast_request().

struct aji_client_container clients

Definition at line 175 of file res_jabber.c.

Referenced by aji_create_client(), aji_do_debug(), aji_no_debug(), aji_reload(), aji_show_clients(), aji_test(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), load_module(), and unload_module().

char debug_usage[] [static]

Initial value:

 
"Usage: jabber debug\n" 
"       Enables dumping of Jabber packets for debugging purposes.\n"

Definition at line 114 of file res_jabber.c.

struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER } [static]

Global flags, initialized to default values.

Definition at line 179 of file res_jabber.c.

char mandescr_jabber_send[] [static]

Definition at line 2380 of file res_jabber.c.

Referenced by load_module().

char no_debug_usage[] [static]

Initial value:

 
"Usage: jabber debug off\n" 
"       Disables dumping of Jabber packets for debugging purposes.\n"

Definition at line 118 of file res_jabber.c.

char reload_usage[] [static]

Initial value:

 
"Usage: jabber reload\n" 
"       Enables reloading of Jabber module.\n"

Definition at line 122 of file res_jabber.c.

char test_usage[] [static]

Initial value:

 
"Usage: jabber test [client]\n" 
"       Sends test message for debugging purposes.  A specific client\n"
"       as configured in jabber.conf can be optionally specified.\n"

Definition at line 126 of file res_jabber.c.

int tls_initialized = FALSE [static]

Definition at line 180 of file res_jabber.c.


Generated on Fri Aug 24 02:28:06 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1