Mon Apr 30 07:46:11 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 JABBER_CONFIG   "jabber.conf"

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)
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
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 []


Detailed Description

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

Definition in file res_jabber.c.


Define Documentation

#define JABBER_CONFIG   "jabber.conf"

Definition at line 55 of file res_jabber.c.

Referenced by aji_load_config().


Function Documentation

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

The action hook parses the inbound packets, constantly running.

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

Definition at line 459 of file res_jabber.c.

References aji_client_connect(), aji_client_destroy(), AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, 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, aji_client::usesasl, and aji_client::usetls.

Referenced by aji_create_client().

00460 {
00461    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00462    ikspak *pak = NULL;
00463    iks *auth = NULL;
00464 
00465    if(!node) {
00466       ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */
00467       ASTOBJ_UNREF(client, aji_client_destroy);
00468       return IKS_HOOK;
00469    }
00470 
00471    pak = iks_packet(node);
00472 
00473    if (!client->component) { /*client */
00474       switch (type) {
00475       case IKS_NODE_START:
00476          if (client->usetls && !iks_is_secure(client->p)) {
00477             if (iks_has_tls())
00478                iks_start_tls(client->p);
00479             else
00480                ast_log(LOG_ERROR, "gnuTLS not installed.\n");
00481             break;
00482          }
00483          if (!client->usesasl) {
00484             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);
00485             auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id"));
00486             if (auth) {
00487                iks_insert_attrib(auth, "id", client->mid);
00488                iks_insert_attrib(auth, "to", client->jid->server);
00489                ast_aji_increment_mid(client->mid);
00490                iks_send(client->p, auth);
00491                iks_delete(auth);
00492             } else
00493                ast_log(LOG_ERROR, "Out of memory.\n");
00494          }
00495          break;
00496 
00497       case IKS_NODE_NORMAL:
00498          {
00499             int features = 0;
00500             if (!strcmp("stream:features", iks_name(node))) {
00501                features = iks_stream_features(node);
00502                if (client->usesasl) {
00503                   if (client->usetls && !iks_is_secure(client->p))
00504                      break;
00505                   if (client->authorized) {
00506                      if (features & IKS_STREAM_BIND) {
00507                         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);
00508                         auth = iks_make_resource_bind(client->jid);
00509                         if (auth) {
00510                            iks_insert_attrib(auth, "id", client->mid);
00511                            ast_aji_increment_mid(client->mid);
00512                            iks_send(client->p, auth);
00513                            iks_delete(auth);
00514                         } else {
00515                            ast_log(LOG_ERROR, "Out of memory.\n");
00516                            break;
00517                         }
00518                      }
00519                      if (features & IKS_STREAM_SESSION) {
00520                         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);
00521                         auth = iks_make_session();
00522                         if (auth) {
00523                            iks_insert_attrib(auth, "id", "auth");
00524                            ast_aji_increment_mid(client->mid);
00525                            iks_send(client->p, auth);
00526                            iks_delete(auth);
00527                         } else {
00528                            ast_log(LOG_ERROR, "Out of memory.\n");
00529                         }
00530                      }
00531                   } else {
00532                      features = aji_highest_bit(features);
00533                      if (features == IKS_STREAM_SASL_MD5)
00534                         iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password);
00535                      else {
00536                         if (features == IKS_STREAM_SASL_PLAIN) {
00537                            iks *x = NULL;
00538                            x = iks_new("auth");
00539                            if (x) {
00540                               iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
00541                               int len = strlen(client->jid->user) + strlen(client->password) + 3;
00542                               /* XXX Check return values XXX */
00543                               char *s = ast_malloc(80 + len);
00544                               char *base64 = ast_malloc(80 + len * 2);
00545                               iks_insert_attrib(x, "mechanism", "PLAIN");
00546                               sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password);
00547                               ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
00548                               iks_insert_cdata(x, base64, 0);
00549                               iks_send(client->p, x);
00550                               iks_delete(x);
00551                               if (base64)
00552                                  free(base64);
00553                               if (s)
00554                                  free(s);
00555                            } else {
00556                               ast_log(LOG_ERROR, "Out of memory.\n");
00557                            }
00558                         }
00559                      }
00560                   }
00561                }
00562             } else if (!strcmp("failure", iks_name(node))) {
00563                ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
00564             } else if (!strcmp("success", iks_name(node))) {
00565                client->authorized = 1;
00566                iks_send_header(client->p, client->jid->server);
00567             }
00568             break;
00569          }
00570       case IKS_NODE_ERROR: 
00571             ast_log(LOG_ERROR, "JABBER: Node Error\n");
00572             ASTOBJ_UNREF(client, aji_client_destroy);
00573             return IKS_HOOK;
00574             break;
00575       case IKS_NODE_STOP: 
00576             ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00577             ASTOBJ_UNREF(client, aji_client_destroy);
00578             return IKS_HOOK;
00579             break;
00580       }
00581    } else if (client->state != AJI_CONNECTED && client->component) {
00582       switch (type) {
00583       case IKS_NODE_START:
00584          if (client->state == AJI_DISCONNECTED) {
00585             char secret[160], shasum[320], *handshake;
00586 
00587             sprintf(secret, "%s%s", pak->id, client->password);
00588             ast_sha1_hash(shasum, secret);
00589             handshake = NULL;
00590             asprintf(&handshake, "<handshake>%s</handshake>", shasum);
00591             if (handshake) {
00592                iks_send_raw(client->p, handshake);
00593                free(handshake);
00594                handshake = NULL;
00595             }
00596             client->state = AJI_CONNECTING;
00597             if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
00598                client->state = AJI_CONNECTED;
00599             else
00600                ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
00601             break;
00602          }
00603          break;
00604 
00605       case IKS_NODE_NORMAL:
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 
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       }
00618    }
00619 
00620    switch (pak->type) {
00621    case IKS_PAK_NONE:
00622       if (option_debug)
00623          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n");
00624       break;
00625    case IKS_PAK_MESSAGE:
00626       aji_handle_message(client, pak);
00627       if (option_debug)
00628          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n");
00629       break;
00630    case IKS_PAK_PRESENCE:
00631       aji_handle_presence(client, pak);
00632       if (option_debug)
00633          ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n");
00634       break;
00635    case IKS_PAK_S10N:
00636       aji_handle_subscribe(client, pak);
00637       if (option_debug)
00638          ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n");
00639       break;
00640    case IKS_PAK_IQ:
00641       if (option_debug)
00642          ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n");
00643       aji_handle_iq(client, node);
00644       break;
00645    default:
00646       if (option_debug)
00647          ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type);
00648       break;
00649    }
00650    
00651    iks_filter_packet(client->f, pak);
00652 
00653    if (node)
00654       iks_delete(node);
00655 
00656    ASTOBJ_UNREF(client, aji_client_destroy);
00657    return IKS_OK;
00658 }

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 197 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().

00198 {
00199    struct aji_resource *tmp;
00200 
00201    while ((tmp = obj->resources)) {
00202       obj->resources = obj->resources->next;
00203       free(tmp->description);
00204       free(tmp);
00205    }
00206 
00207    free(obj);
00208 }

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 1785 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().

01786 {
01787    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01788    int res = 0;
01789 
01790    if (client) {
01791       if (client->state == AJI_DISCONNECTED) {
01792          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);
01793          client->state = AJI_CONNECTING;
01794          client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
01795          iks_filter_remove_hook(client->f, aji_client_connect);
01796          if(!client->component) /*client*/
01797             aji_get_roster(client);
01798       }
01799    } else
01800       ast_log(LOG_ERROR, "Out of memory.\n");
01801 
01802    ASTOBJ_UNREF(client, aji_client_destroy);
01803    return res;
01804 }

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 173 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().

00174 {
00175    struct aji_message *tmp;
00176    ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy);
00177    ASTOBJ_CONTAINER_DESTROY(&obj->buddies);
00178    iks_filter_delete(obj->f);
00179    iks_parser_delete(obj->p);
00180    iks_stack_delete(obj->stack);
00181    AST_LIST_LOCK(&obj->messages);
00182    while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) {
00183       if (tmp->from)
00184          free(tmp->from);
00185       if (tmp->message)
00186          free(tmp->message);
00187    }
00188    AST_LIST_HEAD_DESTROY(&obj->messages);
00189    free(obj);
00190 }

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

Definition at line 865 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().

00866 {
00867    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00868    struct aji_resource *resource = NULL;
00869    struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00870 
00871    resource = aji_find_resource(buddy, pak->from->resource);
00872    if (pak->subtype == IKS_TYPE_RESULT) {
00873       if (!resource) {
00874          ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00875          ASTOBJ_UNREF(client, aji_client_destroy);
00876          return IKS_FILTER_EAT;
00877       }
00878       if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00879          resource->cap->jingle = 1;
00880       } else
00881          resource->cap->jingle = 0;
00882    } else if (pak->subtype == IKS_TYPE_GET) {
00883       iks *iq, *disco, *ident, *google, *query;
00884       iq = iks_new("iq");
00885       query = iks_new("query");
00886       ident = iks_new("identity");
00887       disco = iks_new("feature");
00888       google = iks_new("feature");
00889       if (iq && ident && disco && google) {
00890          iks_insert_attrib(iq, "from", client->jid->full);
00891          iks_insert_attrib(iq, "to", pak->from->full);
00892          iks_insert_attrib(iq, "type", "result");
00893          iks_insert_attrib(iq, "id", pak->id);
00894          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
00895          iks_insert_attrib(ident, "category", "client");
00896          iks_insert_attrib(ident, "type", "pc");
00897          iks_insert_attrib(ident, "name", "asterisk");
00898          iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
00899          iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
00900          iks_insert_node(iq, query);
00901          iks_insert_node(query, ident);
00902          iks_insert_node(query, google);
00903          iks_insert_node(query, disco);
00904          iks_send(client->p, iq);
00905       } else
00906          ast_log(LOG_ERROR, "Out of Memory.\n");
00907       if (iq)
00908          iks_delete(iq);
00909       if (query)
00910          iks_delete(query);
00911       if (ident)
00912          iks_delete(ident);
00913       if (google)
00914          iks_delete(google);
00915       if (disco)
00916          iks_delete(disco);
00917    } else if (pak->subtype == IKS_TYPE_ERROR) {
00918       ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full);
00919    }
00920    ASTOBJ_UNREF(client, aji_client_destroy);
00921    return IKS_FILTER_EAT;
00922 }

static int aji_client_initialize ( struct aji_client client  )  [static]

prepares client for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1811 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().

01812 {
01813    int connected = 0;
01814 
01815    connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server);
01816 
01817    if (connected == IKS_NET_NOCONN) {
01818       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01819       return IKS_HOOK;
01820    } else   if (connected == IKS_NET_NODNS) {
01821       ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01822       return IKS_HOOK;
01823    } else
01824       iks_recv(client->p, 30);
01825    return IKS_OK;
01826 }

static int aji_component_initialize ( struct aji_client client  )  [static]

prepares component for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1833 of file res_jabber.c.

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

Referenced by aji_reconnect().

01834 {
01835    int connected = 1;
01836    connected = iks_connect_via(client->p, client->jid->server, client->port, client->user);
01837    if (connected == IKS_NET_NOCONN) {
01838       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01839       return IKS_HOOK;
01840    } else if (connected == IKS_NET_NODNS) {
01841       ast_log(LOG_ERROR, "JABBER ERROR: No DNS\n");
01842       return IKS_HOOK;
01843    } else if (!connected) 
01844       iks_recv(client->p, 30);
01845    return IKS_OK;
01846 }

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 2222 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().

02223 {
02224    struct aji_buddy *buddy = NULL;
02225    int flag = 0;
02226    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
02227    if (!buddy) {
02228       flag = 1;
02229       buddy = malloc(sizeof(struct aji_buddy));
02230       if(!buddy) {
02231          ast_log(LOG_WARNING, "Out of memory\n");
02232          return 0;
02233       }
02234       memset(buddy, 0, sizeof(struct aji_buddy));
02235       ASTOBJ_INIT(buddy);
02236    }
02237    ASTOBJ_WRLOCK(buddy);
02238    ast_copy_string(buddy->name, label, sizeof(buddy->name));
02239    ASTOBJ_UNLOCK(buddy);
02240    if(flag)
02241       ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
02242    else {
02243       ASTOBJ_UNMARK(buddy);
02244       ASTOBJ_UNREF(buddy, aji_buddy_destroy);
02245    }
02246    return 1;
02247 }

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 2032 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().

02033 {
02034    char *resource;
02035    struct aji_client *client = NULL;
02036    int flag = 0;
02037 
02038    client = ASTOBJ_CONTAINER_FIND(&clients,label);
02039    if (!client) {
02040       flag = 1;
02041       client = (struct aji_client *) malloc(sizeof(struct aji_client));
02042       if (!client) {
02043          ast_log(LOG_ERROR, "Out of memory!\n");
02044          return 0;
02045       }
02046       memset(client, 0, sizeof(struct aji_client));
02047       ASTOBJ_INIT(client);
02048       ASTOBJ_WRLOCK(client);
02049       ASTOBJ_CONTAINER_INIT(&client->buddies);
02050    } else {
02051       ASTOBJ_WRLOCK(client);
02052       ASTOBJ_UNMARK(client);
02053    }
02054    ASTOBJ_CONTAINER_MARKALL(&client->buddies);
02055    ast_copy_string(client->name, label, sizeof(client->name));
02056    ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
02057 
02058    client->debug = debug;
02059    ast_copy_flags(client, &globalflags, AST_FLAGS_ALL);
02060    client->port = 5222;
02061    client->usetls = 1;
02062    client->usesasl = 1;
02063    client->forcessl = 0;
02064    client->keepalive = 1;
02065    client->timeout = 50;
02066    client->message_timeout = 100;
02067    AST_LIST_HEAD_INIT(&client->messages);
02068    client->component = 0;
02069    ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage));
02070 
02071    if (flag) {
02072       client->authorized = 0;
02073       client->state = AJI_DISCONNECTED;
02074    }
02075    while (var) {
02076       if (!strcasecmp(var->name, "username"))
02077          ast_copy_string(client->user, var->value, sizeof(client->user));
02078       else if (!strcasecmp(var->name, "serverhost"))
02079          ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost));
02080       else if (!strcasecmp(var->name, "secret"))
02081          ast_copy_string(client->password, var->value, sizeof(client->password));
02082       else if (!strcasecmp(var->name, "statusmessage"))
02083          ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage));
02084       else if (!strcasecmp(var->name, "port"))
02085          client->port = atoi(var->value);
02086       else if (!strcasecmp(var->name, "timeout"))
02087          client->message_timeout = atoi(var->value);
02088       else if (!strcasecmp(var->name, "debug"))
02089          client->debug = (ast_false(var->value)) ? 0 : 1;
02090       else if (!strcasecmp(var->name, "type")) {
02091          if (!strcasecmp(var->value, "component"))
02092             client->component = 1;
02093       } else if (!strcasecmp(var->name, "usetls")) {
02094          client->usetls = (ast_false(var->value)) ? 0 : 1;
02095       } else if (!strcasecmp(var->name, "usesasl")) {
02096          client->usesasl = (ast_false(var->value)) ? 0 : 1;
02097       } else if (!strcasecmp(var->name, "forceoldssl"))
02098          client->forcessl = (ast_false(var->value)) ? 0 : 1;
02099       else if (!strcasecmp(var->name, "keepalive"))
02100          client->keepalive = (ast_false(var->value)) ? 0 : 1;
02101       else if (!strcasecmp(var->name, "autoprune"))
02102          ast_set2_flag(client, ast_true(var->value), AJI_AUTOPRUNE);
02103       else if (!strcasecmp(var->name, "autoregister"))
02104          ast_set2_flag(client, ast_true(var->value), AJI_AUTOREGISTER);
02105       else if (!strcasecmp(var->name, "buddy"))
02106             aji_create_buddy(var->value, client);
02107    /* no transport support in this version */
02108    /* else if (!strcasecmp(var->name, "transport"))
02109             aji_create_transport(var->value, client);
02110    */
02111       var = var->next;
02112    }
02113    if (!flag) {
02114       ASTOBJ_UNLOCK(client);
02115       ASTOBJ_UNREF(client, aji_client_destroy);
02116       return 1;
02117    }
02118    client->p = iks_stream_new(((client->component) ? "jabber:component:accept" : "jabber:client"), client, aji_act_hook);
02119    if (!client->p) {
02120       ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name);
02121       return 0;
02122    }
02123    client->stack = iks_stack_new(8192, 8192);
02124    if (!client->stack) {
02125       ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name);
02126       return 0;
02127    }
02128    client->f = iks_filter_new();
02129    if (!client->f) {
02130       ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name);
02131       return 0;
02132    }
02133    if (!strchr(client->user, '/') && !client->component) { /*client */
02134       resource = NULL;
02135       asprintf(&resource, "%s/asterisk", client->user);
02136       if (resource) {
02137          client->jid = iks_id_new(client->stack, resource);
02138          free(resource);
02139       }
02140    } else
02141       client->jid = iks_id_new(client->stack, client->user);
02142    if (client->component) {
02143       iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
02144       iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
02145       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);
02146       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);
02147    } else {
02148       iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
02149    }
02150    if (!strchr(client->user, '/') && !client->component) { /*client */
02151       resource = NULL;
02152       asprintf(&resource, "%s/asterisk", client->user);
02153       if (resource) {
02154          client->jid = iks_id_new(client->stack, resource);
02155          free(resource);
02156       }
02157    } else
02158       client->jid = iks_id_new(client->stack, client->user);
02159    iks_set_log_hook(client->p, aji_log_hook);
02160    ASTOBJ_UNLOCK(client);
02161    ASTOBJ_CONTAINER_LINK(&clients,client);
02162    return 1;
02163 }

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

Definition at line 924 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().

00925 {
00926    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00927    char *node = NULL;
00928    struct aji_resource *resource = NULL;
00929    struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00930 
00931    resource = aji_find_resource(buddy, pak->from->resource);
00932    if (pak->subtype == IKS_TYPE_ERROR) {
00933       ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n");
00934       return IKS_FILTER_EAT;
00935    }
00936    if (pak->subtype == IKS_TYPE_RESULT) {
00937       if (!resource) {
00938          ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full);
00939          ASTOBJ_UNREF(client, aji_client_destroy);
00940          return IKS_FILTER_EAT;
00941       }
00942       if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
00943          resource->cap->jingle = 1;
00944       } else
00945          resource->cap->jingle = 0;
00946    } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) {
00947       iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search;
00948 
00949       iq = iks_new("iq");
00950       query = iks_new("query");
00951       identity = iks_new("identity");
00952       disco = iks_new("feature");
00953       reg = iks_new("feature");
00954       commands = iks_new("feature");
00955       gateway = iks_new("feature");
00956       version = iks_new("feature");
00957       vcard = iks_new("feature");
00958       search = iks_new("feature");
00959 
00960       if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) {
00961          iks_insert_attrib(iq, "from", client->user);
00962          iks_insert_attrib(iq, "to", pak->from->full);
00963          iks_insert_attrib(iq, "id", pak->id);
00964          iks_insert_attrib(iq, "type", "result");
00965          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
00966          iks_insert_attrib(identity, "category", "gateway");
00967          iks_insert_attrib(identity, "type", "pstn");
00968          iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX");
00969          iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco");
00970          iks_insert_attrib(reg, "var", "jabber:iq:register");
00971          iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
00972          iks_insert_attrib(gateway, "var", "jabber:iq:gateway");
00973          iks_insert_attrib(version, "var", "jabber:iq:version");
00974          iks_insert_attrib(vcard, "var", "vcard-temp");
00975          iks_insert_attrib(search, "var", "jabber:iq:search");
00976 
00977          iks_insert_node(iq, query);
00978          iks_insert_node(query, identity);
00979          iks_insert_node(query, disco);
00980          iks_insert_node(query, reg);
00981          iks_insert_node(query, commands);
00982          iks_insert_node(query, gateway);
00983          iks_insert_node(query, version);
00984          iks_insert_node(query, vcard);
00985          iks_insert_node(query, search);
00986          iks_send(client->p, iq);
00987       } else {
00988          ast_log(LOG_ERROR, "Out of memory.\n");
00989       }
00990 
00991       if (iq)
00992          iks_delete(iq);
00993       if (query)
00994          iks_delete(query);
00995       if (identity)
00996          iks_delete(identity);
00997       if (disco)
00998          iks_delete(disco);
00999       if (reg)
01000          iks_delete(reg);
01001       if (commands)
01002          iks_delete(commands);
01003       if (gateway)
01004          iks_delete(gateway);
01005       if (version)
01006          iks_delete(version);
01007       if (vcard)
01008          iks_delete(vcard);
01009       if (search)
01010          iks_delete(search);
01011 
01012    } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) {
01013       iks *iq, *query, *confirm;
01014       iq = iks_new("iq");
01015       query = iks_new("query");
01016       confirm = iks_new("item");
01017 
01018       if (iq && query && confirm && client) {
01019          iks_insert_attrib(iq, "from", client->user);
01020          iks_insert_attrib(iq, "to", pak->from->full);
01021          iks_insert_attrib(iq, "id", pak->id);
01022          iks_insert_attrib(iq, "type", "result");
01023          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
01024          iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
01025          iks_insert_attrib(confirm, "node", "confirmaccount");
01026          iks_insert_attrib(confirm, "name", "Confirm AIM account");
01027          iks_insert_attrib(confirm, "jid", client->user);
01028          iks_insert_node(iq, query);
01029          iks_insert_node(query, confirm);
01030          iks_send(client->p, iq);
01031       } else {
01032          ast_log(LOG_ERROR, "Out of memory.\n");
01033       }
01034       if (iq)
01035          iks_delete(iq);
01036       if (query)
01037          iks_delete(query);
01038       if (confirm)
01039          iks_delete(confirm);
01040 
01041    } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) {
01042       iks *iq, *query, *feature;
01043 
01044       iq = iks_new("iq");
01045       query = iks_new("query");
01046       feature = iks_new("feature");
01047 
01048       if (iq && query && feature && client) {
01049          iks_insert_attrib(iq, "from", client->user);
01050          iks_insert_attrib(iq, "to", pak->from->full);
01051          iks_insert_attrib(iq, "id", pak->id);
01052          iks_insert_attrib(iq, "type", "result");
01053          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01054          iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
01055          iks_insert_node(iq, query);
01056          iks_insert_node(query, feature);
01057          iks_send(client->p, iq);
01058       } else {
01059          ast_log(LOG_ERROR, "Out of memory.\n");
01060       }
01061       if (iq)
01062          iks_delete(iq);
01063       if (query)
01064          iks_delete(query);
01065       if (feature)
01066          iks_delete(feature);
01067    }
01068 
01069    ASTOBJ_UNREF(client, aji_client_destroy);
01070    return IKS_FILTER_EAT;
01071 }

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

Definition at line 769 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().

00770 {
00771    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00772    char *node = NULL;
00773 
00774    if (!(node = iks_find_attrib(pak->query, "node"))) {
00775       iks *iq = NULL, *query = NULL, *item = NULL;
00776       iq = iks_new("iq");
00777       query = iks_new("query");
00778       item = iks_new("item");
00779 
00780       if (iq && query && item) {
00781          iks_insert_attrib(iq, "from", client->user);
00782          iks_insert_attrib(iq, "to", pak->from->full);
00783          iks_insert_attrib(iq, "id", pak->id);
00784          iks_insert_attrib(iq, "type", "result");
00785          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00786          iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
00787          iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands");
00788          iks_insert_attrib(item, "jid", client->user);
00789 
00790          iks_insert_node(iq, query);
00791          iks_insert_node(query, item);
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 (item)
00801          iks_delete(item);
00802 
00803    } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
00804       iks *iq, *query, *confirm;
00805       iq = iks_new("iq");
00806       query = iks_new("query");
00807       confirm = iks_new("item");
00808       if (iq && query && confirm && client) {
00809          iks_insert_attrib(iq, "from", client->user);
00810          iks_insert_attrib(iq, "to", pak->from->full);
00811          iks_insert_attrib(iq, "id", pak->id);
00812          iks_insert_attrib(iq, "type", "result");
00813          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00814          iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
00815          iks_insert_attrib(confirm, "node", "confirmaccount");
00816          iks_insert_attrib(confirm, "name", "Confirm AIM account");
00817          iks_insert_attrib(confirm, "jid", "blog.astjab.org");
00818 
00819          iks_insert_node(iq, query);
00820          iks_insert_node(query, confirm);
00821          iks_send(client->p, iq);
00822       } else {
00823          ast_log(LOG_ERROR, "Out of memory.\n");
00824       }
00825       if (iq)
00826          iks_delete(iq);
00827       if (query)
00828          iks_delete(query);
00829       if (confirm)
00830          iks_delete(confirm);
00831 
00832    } else if (!strcasecmp(node, "confirmaccount")) {
00833       iks *iq = NULL, *query = NULL, *feature = NULL;
00834 
00835       iq = iks_new("iq");
00836       query = iks_new("query");
00837       feature = iks_new("feature");
00838 
00839       if (iq && query && feature && client) {
00840          iks_insert_attrib(iq, "from", client->user);
00841          iks_insert_attrib(iq, "to", pak->from->full);
00842          iks_insert_attrib(iq, "id", pak->id);
00843          iks_insert_attrib(iq, "type", "result");
00844          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00845          iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
00846          iks_insert_node(iq, query);
00847          iks_insert_node(query, feature);
00848          iks_send(client->p, iq);
00849       } else {
00850          ast_log(LOG_ERROR, "Out of memory.\n");
00851       }
00852       if (iq)
00853          iks_delete(iq);
00854       if (query)
00855          iks_delete(query);
00856       if (feature)
00857          iks_delete(feature);
00858    }
00859 
00860    ASTOBJ_UNREF(client, aji_client_destroy);
00861    return IKS_FILTER_EAT;
00862 
00863 }

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 1903 of file res_jabber.c.

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

01904 {
01905    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01906       ASTOBJ_RDLOCK(iterator); 
01907       iterator->debug = 1;
01908       ASTOBJ_UNLOCK(iterator);
01909    });
01910    ast_cli(fd, "Jabber Debugging Enabled.\n");
01911    return RESULT_SUCCESS;
01912 }

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 1919 of file res_jabber.c.

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

01920 {
01921    aji_reload();
01922    ast_cli(fd, "Jabber Reloaded.\n");
01923    return RESULT_SUCCESS;
01924 }

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 1674 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().

01675 {
01676    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01677    int flag = 0;
01678    iks *x = NULL;
01679    struct aji_buddy *buddy;
01680    
01681    client->state = AJI_CONNECTED;
01682    ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01683       ASTOBJ_RDLOCK(iterator);
01684       x = iks_child(pak->query);
01685       flag = 0;
01686       while (x) {
01687          if (!iks_strcmp(iks_name(x), "item")) {
01688             if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
01689                flag = 1;
01690                ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
01691             }
01692          }
01693          x = iks_next(x);
01694       }
01695       if (!flag)
01696          ast_copy_flags(iterator, client, AJI_AUTOREGISTER);
01697       if (x)
01698          iks_delete(x);
01699       ASTOBJ_UNLOCK(iterator);
01700    });
01701 
01702    x = iks_child(pak->query);
01703    while (x) {
01704       flag = 0;
01705       if (iks_strcmp(iks_name(x), "item") == 0) {
01706          ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01707             ASTOBJ_RDLOCK(iterator);
01708             if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
01709                flag = 1;
01710             ASTOBJ_UNLOCK(iterator);
01711          });
01712 
01713          if (!flag) {
01714             buddy = (struct aji_buddy *) malloc(sizeof(struct aji_buddy));
01715             if (!buddy) {
01716                ast_log(LOG_WARNING, "Out of memory\n");
01717                return 0;
01718             }
01719             memset(buddy, 0, sizeof(struct aji_buddy));
01720             ASTOBJ_INIT(buddy);
01721             ASTOBJ_WRLOCK(buddy);
01722             ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name));
01723             ast_clear_flag(buddy, AST_FLAGS_ALL);
01724             if(ast_test_flag(client, AJI_AUTOPRUNE)) {
01725                ast_set_flag(buddy, AJI_AUTOPRUNE);
01726                buddy->objflags |= ASTOBJ_FLAG_MARKED;
01727             } else
01728                ast_set_flag(buddy, AJI_AUTOREGISTER);
01729             ASTOBJ_UNLOCK(buddy);
01730             if (buddy) {
01731                ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
01732                ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01733             }
01734          }
01735       }
01736       x = iks_next(x);
01737    }
01738    if (x)
01739       iks_delete(x);
01740    aji_pruneregister(client);
01741 
01742    ASTOBJ_UNREF(client, aji_client_destroy);
01743    return IKS_FILTER_EAT;
01744 }

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

Definition at line 268 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().

00269 {
00270    struct aji_resource *res = NULL;
00271    if (!buddy || !name)
00272       return res;
00273    res = buddy->resources;
00274    while (res) {
00275       if (!strcasecmp(res->resource, name)) {
00276          break;
00277       }
00278       res = res->next;
00279    }
00280    return res;
00281 }

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

Definition at line 210 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().

00211 {
00212    struct aji_capabilities *list = NULL;
00213    struct aji_version *res = NULL;
00214 
00215    list = capabilities;
00216 
00217    if(!node)
00218       node = pak->from->full;
00219    if(!version)
00220       version = "none supplied.";
00221    while(list) {
00222       if(!strcasecmp(list->node, node)) {
00223          res = list->versions;
00224          while(res) {
00225              if(!strcasecmp(res->version, version))
00226                 return res;
00227              res = res->next;
00228          }
00229          if(!res) {
00230             res = (struct aji_version *)malloc(sizeof(struct aji_version));
00231             if(!res) {
00232                ast_log(LOG_ERROR, "Out of memory!\n");
00233                return NULL;
00234             }
00235             res->jingle = 0;
00236             res->parent = list;
00237             ast_copy_string(res->version, version, sizeof(res->version));
00238             res->next = list->versions;
00239             list->versions = res;
00240             return res;
00241          }
00242       }
00243       list = list->next;
00244    }
00245    if(!list) {
00246       list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities));
00247       if(!list) {
00248          ast_log(LOG_ERROR, "Out of memory!\n");
00249          return NULL;
00250       }
00251       res = (struct aji_version *)malloc(sizeof(struct aji_version));
00252       if(!res) {
00253          ast_log(LOG_ERROR, "Out of memory!\n");
00254          return NULL;
00255       }
00256       ast_copy_string(list->node, node, sizeof(list->node));
00257       ast_copy_string(res->version, version, sizeof(res->version));
00258       res->jingle = 0;
00259       res->parent = list;
00260       res->next = list->versions;
00261       list->versions = res;
00262       list->next = capabilities;
00263       capabilities = list;
00264    }
00265    return res;
00266 }

static int aji_get_roster ( struct aji_client client  )  [static]

Definition at line 1766 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().

01767 {
01768    iks *roster = NULL;
01769    roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
01770    if(roster) {
01771       iks_insert_attrib(roster, "id", "roster");
01772       aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
01773       iks_send(client->p, roster);
01774    }
01775    if (roster)
01776       iks_delete(roster);
01777    return 1;
01778 }

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 1078 of file res_jabber.c.

Referenced by aji_act_hook().

01079 {
01080    /*Nothing to see here */
01081 }

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 1088 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().

01089 {
01090    struct aji_message *insert, *tmp;
01091    int flag = 0;
01092    
01093    if (!(insert = ast_calloc(1, sizeof(struct aji_message))))
01094       return;
01095    time(&insert->arrived);
01096    if (iks_find_cdata(pak->x, "body"))
01097       insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
01098    if(pak->id)
01099       ast_copy_string(insert->id, pak->id, sizeof(insert->message));
01100    if (pak->from)
01101       insert->from = ast_strdup(pak->from->full);
01102    AST_LIST_LOCK(&client->messages);
01103    AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
01104       if (flag) {
01105          AST_LIST_REMOVE_CURRENT(&client->messages, list);
01106          if (tmp->from)
01107             free(tmp->from);
01108          if (tmp->message)
01109             free(tmp->message);
01110       } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
01111          flag = 1;
01112          AST_LIST_REMOVE_CURRENT(&client->messages, list);
01113          if (tmp->from)
01114             free(tmp->from);
01115          if (tmp->message)
01116             free(tmp->message);
01117       }
01118    }
01119    AST_LIST_TRAVERSE_SAFE_END;
01120    AST_LIST_INSERT_HEAD(&client->messages, insert, list);
01121    AST_LIST_UNLOCK(&client->messages);
01122 }

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

Definition at line 1124 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().

01125 {
01126    int status, priority;
01127    struct aji_buddy *buddy;
01128    struct aji_resource *tmp = NULL, *last = NULL, *found = NULL;
01129    char *ver, *node, *descrip, *type;
01130    
01131    if(client->state != AJI_CONNECTED)
01132       aji_create_buddy(pak->from->partial, client);
01133 
01134    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
01135    if (!buddy) {
01136       ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial);
01137       return;
01138    }
01139    type = iks_find_attrib(pak->x, "type");
01140    if(client->component && type &&!strcasecmp("probe", type)) {
01141       aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01142       ast_verbose("what i was looking for \n");
01143    }
01144    ASTOBJ_WRLOCK(buddy);
01145    status = (pak->show) ? pak->show : 6;
01146    priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
01147    tmp = buddy->resources;
01148    descrip = ast_strdup(iks_find_cdata(pak->x,"status"));
01149 
01150    while (tmp) {
01151       if (!strcasecmp(tmp->resource, pak->from->resource)) {
01152          tmp->status = status;
01153          if (tmp->description) free(tmp->description);
01154          tmp->description = descrip;
01155          found = tmp;
01156          if (status == 6) {   /* Sign off Destroy resource */
01157             if (last && found->next) {
01158                last->next = found->next;
01159             } else if (!last) {
01160                if (found->next)
01161                   buddy->resources = found->next;
01162                else
01163                   buddy->resources = NULL;
01164             } else if (!found->next) {
01165                if (last)
01166                   last->next = NULL;
01167                else
01168                   buddy->resources = NULL;
01169             }
01170             free(found);
01171             found = NULL;
01172             break;
01173          }
01174          if (tmp->priority != priority) {
01175             found->priority = priority;
01176             if (!last && !found->next)
01177                break;
01178             if (last)
01179                last->next = found->next;
01180             else
01181                buddy->resources = found->next;
01182             last = NULL;
01183             tmp = buddy->resources;
01184             if (!buddy->resources)
01185                buddy->resources = found;
01186             while (tmp) {
01187                if (found->priority > tmp->priority) {
01188                   if (last)
01189                      last->next = found;
01190                   found->next = tmp;
01191                   if (!last)
01192                      buddy->resources = found;
01193                   break;
01194                }
01195                if (!tmp->next) {
01196                   tmp->next = found;
01197                   break;
01198                }
01199                last = tmp;
01200                tmp = tmp->next;
01201             }
01202          }
01203          break;
01204       }
01205       last = tmp;
01206       tmp = tmp->next;
01207    }
01208 
01209    if (!found && status != 6) {
01210       found = (struct aji_resource *) malloc(sizeof(struct aji_resource));
01211       memset(found, 0, sizeof(struct aji_resource));
01212 
01213       if (!found) {
01214          ast_log(LOG_ERROR, "Out of memory!\n");
01215          return;
01216       }
01217       ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource));
01218       found->status = status;
01219       found->description = descrip;
01220       found->priority = priority;
01221       found->next = NULL;
01222       last = NULL;
01223       tmp = buddy->resources;
01224       while (tmp) {
01225          if (found->priority > tmp->priority) {
01226             if (last)
01227                last->next = found;
01228             found->next = tmp;
01229             if (!last)
01230                buddy->resources = found;
01231             break;
01232          }
01233          if (!tmp->next) {
01234             tmp->next = found;
01235             break;
01236          }
01237          last = tmp;
01238          tmp = tmp->next;
01239       }
01240       if (!tmp)
01241          buddy->resources = found;
01242    }
01243    ASTOBJ_UNLOCK(buddy);
01244    ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01245 
01246    node = iks_find_attrib(iks_find(pak->x, "c"), "node");
01247    ver = iks_find_attrib(iks_find(pak->x, "c"), "ver");
01248 
01249    if(status !=6 && !found->cap) {
01250       found->cap = aji_find_version(node, ver, pak);
01251       if(gtalk_yuck(pak->x)) /* gtalk should do discover */
01252          found->cap->jingle = 1;
01253       if(found->cap->jingle && option_debug > 4)
01254          ast_log(LOG_DEBUG,"Special case for google till they support discover.\n");
01255       else {
01256          iks *iq, *query;
01257          iq = iks_new("iq");
01258          query = iks_new("query");
01259          if(query && iq)  {
01260             iks_insert_attrib(iq, "type", "get");
01261             iks_insert_attrib(iq, "to", pak->from->full);
01262             iks_insert_attrib(iq,"from",iks_find_attrib(pak->x,"to"));
01263             iks_insert_attrib(iq, "id", client->mid);
01264             ast_aji_increment_mid(client->mid);
01265             iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
01266             iks_insert_node(iq, query);
01267             iks_send(client->p, iq);
01268             
01269          } else
01270             ast_log(LOG_ERROR, "Out of memory.\n");
01271          if(query)
01272             iks_delete(query);
01273          if(iq)
01274             iks_delete(iq);
01275       }
01276    }
01277    if (option_verbose > 4) {
01278       switch (pak->subtype) {
01279       case IKS_TYPE_AVAILABLE:
01280          ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am available ^_* %i\n", pak->subtype);
01281          break;
01282       case IKS_TYPE_UNAVAILABLE:
01283          ast_verbose(VERBOSE_PREFIX_3 "JABBER: I am unavailable ^_* %i\n", pak->subtype);
01284          break;
01285       default:
01286          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype);
01287       }
01288       switch (pak->show) {
01289       case IKS_SHOW_UNAVAILABLE:
01290          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01291          break;
01292       case IKS_SHOW_AVAILABLE:
01293          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is available\n");
01294          break;
01295       case IKS_SHOW_CHAT:
01296          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01297          break;
01298       case IKS_SHOW_AWAY:
01299          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type is away\n");
01300          break;
01301       case IKS_SHOW_XA:
01302          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01303          break;
01304       case IKS_SHOW_DND:
01305          ast_verbose(VERBOSE_PREFIX_3 "JABBER: type: %i subtype %i\n", pak->subtype, pak->show);
01306          break;
01307       default:
01308          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Kinky! how did that happen %i\n", pak->show);
01309       }
01310    }
01311 }

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 1318 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().

01319 {
01320    if(pak->subtype == IKS_TYPE_SUBSCRIBE) { 
01321       iks *presence = NULL, *status = NULL;
01322       presence = iks_new("presence");
01323       status = iks_new("status");
01324       if(presence && status) {
01325          iks_insert_attrib(presence, "type", "subscribed");
01326          iks_insert_attrib(presence, "to", pak->from->full);
01327          iks_insert_attrib(presence, "from", client->jid->full);
01328          if(pak->id)
01329             iks_insert_attrib(presence, "id", pak->id);
01330          iks_insert_cdata(status, "Asterisk has approved subscription", 0);
01331          iks_insert_node(presence, status);
01332          iks_send(client->p, presence);
01333       } else
01334          ast_log(LOG_ERROR, "Unable to allocate nodes\n");
01335       if(presence)
01336          iks_delete(presence);
01337       if(status)
01338          iks_delete(status);
01339       if(client->component)
01340          aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01341    }
01342    if (option_verbose > 4) {
01343       switch (pak->subtype) {
01344       case IKS_TYPE_SUBSCRIBE:
01345          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01346          break;
01347       case IKS_TYPE_SUBSCRIBED:
01348          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01349          break;
01350       case IKS_TYPE_UNSUBSCRIBE:
01351          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01352          break;
01353       case IKS_TYPE_UNSUBSCRIBED:
01354          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01355          break;
01356       default:          /*IKS_TYPE_ERROR: */
01357          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01358          break;
01359       }
01360    }
01361 }

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 295 of file res_jabber.c.

Referenced by aji_act_hook().

00296 {
00297    int x = sizeof(number) * 8 - 1;
00298    if (!number)
00299       return 0;
00300    for (; x > 0; x--) {
00301       if (number & (1 << x))
00302          break;
00303    }
00304    return (1 << x);
00305 }

static int aji_load_config ( void   )  [static]

load config file.

Parameters:
void. 
Returns:
1.

Definition at line 2254 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().

02255 {
02256    char *cat = NULL;
02257    int debug = 1;
02258    struct ast_config *cfg = NULL;
02259    struct ast_variable *var = NULL;
02260 
02261    cfg = ast_config_load(JABBER_CONFIG);
02262    if (!cfg) {
02263       ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
02264       return 0;
02265    }
02266 
02267    cat = ast_category_browse(cfg, NULL);
02268    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02269       if (!strcasecmp(var->name, "debug"))
02270          debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1;
02271       else if (!strcasecmp(var->name, "autoprune"))
02272          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE);
02273       else if (!strcasecmp(var->name, "autoregister"))
02274          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER);
02275    }
02276 
02277    while (cat) {
02278       if (strcasecmp(cat, "general")) {
02279             var = ast_variable_browse(cfg, cat);
02280             aji_create_client(cat, var, debug);
02281       }
02282       cat = ast_category_browse(cfg, cat);
02283    }
02284    return 1;
02285 }

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 434 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().

00435 {
00436    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00437    manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
00438 
00439    if (client->debug) {
00440       if (is_incoming)
00441          ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
00442       else {
00443          if( strlen(xmpp) == 1) {
00444             if(option_debug > 2  && xmpp[0] == ' ')
00445             ast_verbose("\nJABBER: Keep alive packet\n");
00446          } else
00447             ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
00448       }
00449 
00450    }
00451    ASTOBJ_UNREF(client, aji_client_destroy);
00452 }

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 1931 of file res_jabber.c.

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

01932 {
01933    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01934       ASTOBJ_RDLOCK(iterator);
01935       iterator->debug = 0;
01936       ASTOBJ_UNLOCK(iterator);
01937    });
01938    ast_cli(fd, "Jabber Debugging Disabled.\n");
01939    return RESULT_SUCCESS;
01940 }

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 1621 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.

01622 {
01623    int res = 0;
01624    iks *removeiq = iks_new("iq");
01625    iks *removequery = iks_new("query");
01626    iks *removeitem = iks_new("item");
01627    iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items");
01628 
01629    if (client && removeiq && removequery && removeitem && send) {
01630       iks_insert_node(removeiq, removequery);
01631       iks_insert_node(removequery, removeitem);
01632       ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01633          ASTOBJ_RDLOCK(iterator);
01634          /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never
01635           * be called at the same time */
01636          if (ast_test_flag(iterator, AJI_AUTOPRUNE)) {
01637             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
01638                   "GoodBye your status is no longer needed by Asterisk the Open Source PBX"
01639                   " so I am no longer subscribing to your presence.\n"));
01640             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
01641                   "GoodBye you are no longer in the asterisk config file so I am removing"
01642                   " your access to my presence.\n"));
01643             iks_insert_attrib(removeiq, "from", client->jid->full); 
01644             iks_insert_attrib(removeiq, "type", "set"); 
01645             iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster");
01646             iks_insert_attrib(removeitem, "jid", iterator->name);
01647             iks_insert_attrib(removeitem, "subscription", "remove");
01648             res = iks_send(client->p, removeiq);
01649          } else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) {
01650             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 
01651                   "Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
01652             ast_clear_flag(iterator, AJI_AUTOREGISTER);
01653          }
01654          ASTOBJ_UNLOCK(iterator);
01655       });
01656    } else
01657       ast_log(LOG_ERROR, "Out of memory.\n");
01658    if (removeiq)
01659       iks_delete(removeiq);
01660    if (removequery)
01661       iks_delete(removequery);
01662    if (removeitem)
01663       iks_delete(removeitem);
01664    if (send)
01665       iks_delete(send);
01666    ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy);
01667 }

static int aji_reconnect ( struct aji_client client  )  [static]

Definition at line 1746 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().

01747 {
01748    int res = 0;
01749 
01750    if (client->state)
01751       client->state = AJI_DISCONNECTED;
01752    client->timeout=50;
01753    if (client->p)
01754       iks_parser_reset(client->p);
01755    if (client->authorized)
01756       client->authorized = 0;
01757 
01758    if(client->component)
01759       res = aji_component_initialize(client);
01760    else
01761       res = aji_client_initialize(client);
01762 
01763    return res;
01764 }

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

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1476 of file res_jabber.c.

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

Referenced by aji_reload().

01477 {
01478    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01479    int res = IKS_HOOK;
01480    do {
01481       if (res != IKS_OK) {
01482          while(res != IKS_OK) {
01483             if(option_verbose > 3)
01484                ast_verbose("JABBER: reconnecting.\n");
01485             res = aji_reconnect(client);
01486             sleep(4);
01487          }
01488       }
01489 
01490       res = iks_recv(client->p, 1);
01491       client->timeout--;
01492       if (res == IKS_HOOK) 
01493          ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
01494       else if (res == IKS_NET_TLSFAIL)
01495          ast_log(LOG_WARNING, "JABBER:  Failure in TLS.\n");
01496       else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
01497          res = iks_send_raw(client->p, " ");
01498          if(res == IKS_OK)
01499             client->timeout = 50;
01500          else
01501             ast_log(LOG_WARNING, "JABBER:  Network Timeout\n");
01502       } else if (res == IKS_NET_RWERR)
01503          ast_log(LOG_WARNING, "JABBER: socket read error\n");
01504    } while (client);
01505    ASTOBJ_UNREF(client, aji_client_destroy);
01506    return 0;
01507 }

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

Definition at line 660 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().

00661 {
00662    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00663    iks *iq = NULL, *presence = NULL, *x = NULL;
00664 
00665    iq = iks_new("iq");
00666    presence = iks_new("presence");
00667    x = iks_new("x");
00668    if (client && iq && presence && x) {
00669       if (!iks_find(pak->query, "remove")) {
00670          iks_insert_attrib(iq, "from", client->jid->full);
00671          iks_insert_attrib(iq, "to", pak->from->full);
00672          iks_insert_attrib(iq, "id", pak->id);
00673          iks_insert_attrib(iq, "type", "result");
00674          iks_send(client->p, iq);
00675 
00676          iks_insert_attrib(presence, "from", client->jid->full);
00677          iks_insert_attrib(presence, "to", pak->from->partial);
00678          iks_insert_attrib(presence, "id", client->mid);
00679          ast_aji_increment_mid(client->mid);
00680          iks_insert_attrib(presence, "type", "subscribe");
00681          iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
00682          iks_insert_node(presence, x);
00683          iks_send(client->p, presence); 
00684       }
00685    } else {
00686       ast_log(LOG_ERROR, "Out of memory.\n");
00687    }
00688 
00689    if (iq)
00690       iks_delete(iq);
00691    if(presence)
00692       iks_delete(presence);
00693    if (x)
00694       iks_delete(x);
00695    ASTOBJ_UNREF(client, aji_client_destroy);
00696    return IKS_FILTER_EAT;
00697 }

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

Definition at line 699 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().

00700 {
00701    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00702    struct aji_buddy *buddy = NULL; 
00703    char *node = NULL;
00704 
00705    client = (struct aji_client *) data;
00706 
00707    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial);
00708    if (!buddy) {
00709       ast_verbose("Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
00710       iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL;
00711       iq = iks_new("iq");
00712       query = iks_new("query");
00713       error = iks_new("error");
00714       notacceptable = iks_new("not-acceptable");
00715       if(iq && query && error && notacceptable) {
00716          iks_insert_attrib(iq, "type", "error");
00717          iks_insert_attrib(iq, "from", client->user);
00718          iks_insert_attrib(iq, "to", pak->from->full);
00719          iks_insert_attrib(iq, "id", pak->id);
00720          iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00721          iks_insert_attrib(error, "code" , "406");
00722          iks_insert_attrib(error, "type", "modify");
00723          iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
00724          iks_insert_node(iq, query);
00725          iks_insert_node(iq, error);
00726          iks_insert_node(error, notacceptable);
00727          iks_send(client->p, iq);
00728       } else {
00729          ast_log(LOG_ERROR, "Out of memory.\n");
00730       }
00731       if (iq)
00732          iks_delete(iq);
00733       if (query)
00734          iks_delete(query);
00735       if (error)
00736          iks_delete(error);
00737       if (notacceptable)
00738          iks_delete(notacceptable);
00739    } else   if (!(node = iks_find_attrib(pak->query, "node"))) {
00740       iks *iq = NULL, *query = NULL, *instructions = NULL;
00741       char *explain = "Welcome to Asterisk - the Open Source PBX.\n";
00742       iq = iks_new("iq");
00743       query = iks_new("query");
00744       instructions = iks_new("instructions");
00745       if (iq && query && instructions && client) {
00746          iks_insert_attrib(iq, "from", client->user);
00747          iks_insert_attrib(iq, "to", pak->from->full);
00748          iks_insert_attrib(iq, "id", pak->id);
00749          iks_insert_attrib(iq, "type", "result");
00750          iks_insert_attrib(query, "xmlns", "jabber:iq:register");
00751          iks_insert_cdata(instructions, explain, 0);
00752          iks_insert_node(iq, query);
00753          iks_insert_node(query, instructions);
00754          iks_send(client->p, iq);
00755       } else {
00756          ast_log(LOG_ERROR, "Out of memory.\n");
00757       }
00758       if (iq)
00759          iks_delete(iq);
00760       if (query)
00761          iks_delete(query);
00762       if (instructions)
00763          iks_delete(instructions);
00764    }
00765    ASTOBJ_UNREF(client, aji_client_destroy);
00766    return IKS_FILTER_EAT;
00767 }

static int aji_reload ( void   )  [static]

Definition at line 2356 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().

02357 {
02358    ASTOBJ_CONTAINER_MARKALL(&clients);
02359    if (!aji_load_config()) {
02360       ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
02361       return 0;
02362    }
02363    ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
02364    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02365       ASTOBJ_RDLOCK(iterator);
02366       if(iterator->state == AJI_DISCONNECTED) {
02367          if (!iterator->thread)
02368             ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
02369       } else if (iterator->state == AJI_CONNECTING)
02370          aji_get_roster(iterator);
02371       ASTOBJ_UNLOCK(iterator);
02372    });
02373    
02374    return 1;
02375 }

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 398 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().

00399 {
00400    struct aji_client *client = NULL;
00401 
00402    char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL;
00403 
00404    if (!data) {
00405       ast_log(LOG_ERROR, "This application requires arguments.\n");
00406       return 0;
00407    }
00408    s = ast_strdupa(data);
00409    if (s) {
00410       sender = strsep(&s, "|");
00411       if (sender && (sender[0] != '\0')) {
00412          recipient = strsep(&s, "|");
00413          if (recipient && (recipient[0] != '\0')) {
00414             message = s;
00415          } else {
00416             ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data);
00417             return -1;
00418          }
00419       }
00420    }
00421    if (!(client = ast_aji_get_client(sender))) {
00422       ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00423       return -1;
00424    }
00425    if (strchr(recipient, '@') && message)
00426       ast_aji_send(client, recipient, message);
00427    return 0;
00428 }

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 1871 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().

01872 {
01873    int res = 0;
01874    iks *presence = iks_make_pres(level, desc);
01875    iks *cnode = iks_new("c");
01876    iks *priority = iks_new("priority");
01877 
01878    iks_insert_cdata(priority, "0", 1);
01879    if (presence && cnode && client) {
01880       if(to)
01881          iks_insert_attrib(presence, "to", to);
01882       if(from)
01883          iks_insert_attrib(presence, "from", from);
01884       iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
01885       iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
01886       iks_insert_attrib(cnode, "ext", "voice-v1");
01887       iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
01888       iks_insert_node(presence, cnode);
01889       res = iks_send(client->p, presence);
01890    } else
01891       ast_log(LOG_ERROR, "Out of memory.\n");
01892    if (cnode)
01893       iks_delete(cnode);
01894    if (presence)
01895       iks_delete(presence);
01896 }

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 1947 of file res_jabber.c.

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

01948 {
01949    char *status;
01950    int count = 0;
01951    ast_cli(fd, "Jabber Users and their status:\n");
01952    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01953       ASTOBJ_RDLOCK(iterator);
01954       count++;
01955       switch (iterator->state) {
01956       case AJI_DISCONNECTED:
01957          status = "Disconnected";
01958          break;
01959       case AJI_CONNECTING:
01960          status = "Connecting";
01961          break;
01962       case AJI_CONNECTED:
01963          status = "Connected";
01964          break;
01965       default:
01966          status = "Unknown";
01967       }
01968       ast_cli(fd, "       User: %s     - %s\n", iterator->user, status);
01969       ASTOBJ_UNLOCK(iterator);
01970    });
01971    ast_cli(fd, "----\n");
01972    ast_cli(fd, "   Number of users: %d\n", count);
01973    return RESULT_SUCCESS;
01974 }

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 334 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().

00335 {
00336    struct aji_client *client = NULL;
00337    struct aji_buddy *buddy = NULL;
00338    struct aji_resource *r = NULL;
00339    char *s = NULL, *sender = NULL, *jid = NULL, *screenname = NULL, *resource = NULL, *variable = NULL;
00340    int stat = 7;
00341    char status[2];
00342 
00343    if (!data) {
00344       ast_log(LOG_ERROR, "This application requires arguments.\n");
00345       return 0;
00346    }
00347    s = ast_strdupa(data);
00348    if (s) {
00349       sender = strsep(&s, "|");
00350       if (sender && (sender[0] != '\0')) {
00351          jid = strsep(&s, "|");
00352          if (jid && (jid[0] != '\0')) {
00353             variable = s;
00354          } else {
00355             ast_log(LOG_ERROR, "Bad arguments\n");
00356             return -1;
00357          }
00358       }
00359    }
00360 
00361    if(!strchr(jid, '/')) {
00362       resource = NULL;
00363    } else {
00364       screenname = strsep(&jid, "/");
00365       resource = jid;
00366    }
00367    client = ast_aji_get_client(sender);
00368    if (!client) {
00369       ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00370       return -1;
00371    }
00372    if(!&client->buddies) {
00373       ast_log(LOG_WARNING, "No buddies for connection : %s\n", sender);
00374       return -1;
00375    }
00376    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, resource ? screenname: jid);
00377    if (!buddy) {
00378       ast_log(LOG_WARNING, "Could not find buddy in list : %s\n", resource ? screenname : jid);
00379       return -1;
00380    }
00381    r = aji_find_resource(buddy, resource);
00382    if(!r && buddy->resources) 
00383       r = buddy->resources;
00384    if(!r)
00385       ast_log(LOG_NOTICE, "Resource %s of buddy %s not found \n", resource, screenname);
00386    else
00387       stat = r->status;
00388    sprintf(status, "%d", stat);
00389    pbx_builtin_setvar_helper(chan, variable, status);
00390    return 0;
00391 }

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 1981 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.

01982 {
01983    struct aji_client *client;
01984    struct aji_resource *resource;
01985    const char *name = "asterisk";
01986    struct aji_message *tmp;
01987 
01988    if (argc > 3)
01989       return RESULT_SHOWUSAGE;
01990    else if (argc == 3)
01991       name = argv[2];
01992 
01993    if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
01994       ast_cli(fd, "Unable to find client '%s'!\n", name);
01995       return RESULT_FAILURE;
01996    }
01997 
01998    /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */
01999    ast_aji_send(client, "mogorman@astjab.org", "blahblah");
02000    ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02001       ASTOBJ_RDLOCK(iterator);
02002       ast_verbose("User: %s\n", iterator->name);
02003       for (resource = iterator->resources; resource; resource = resource->next) {
02004          ast_verbose("Resource: %s\n", resource->resource);
02005          if(resource->cap) {
02006             ast_verbose("   client: %s\n", resource->cap->parent->node);
02007             ast_verbose("   version: %s\n", resource->cap->version);
02008             ast_verbose("   Jingle Capable: %d\n", resource->cap->jingle);
02009          }
02010          ast_verbose("  Priority: %d\n", resource->priority);
02011          ast_verbose("  Status: %d\n", resource->status); 
02012          ast_verbose("  Message: %s\n", S_OR(resource->description,"")); 
02013       }
02014       ASTOBJ_UNLOCK(iterator);
02015    });
02016    ast_verbose("\nOooh a working message stack!\n");
02017    AST_LIST_LOCK(&client->messages);
02018    AST_LIST_TRAVERSE(&client->messages, tmp, list) {
02019       ast_verbose("  Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, ""));
02020    }
02021    AST_LIST_UNLOCK(&client->messages);
02022    ASTOBJ_UNREF(client, aji_client_destroy);
02023 
02024    return RESULT_SUCCESS;
02025 }

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 1392 of file res_jabber.c.

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

01393 {
01394    int res = 0;
01395    iks *iq = NULL;
01396    iq = iks_new("iq");
01397    if (iq && client) {
01398       iks_insert_attrib(iq, "type", "get");
01399       iks_insert_attrib(iq, "to", server);
01400       iks_insert_attrib(iq, "id", client->mid);
01401       ast_aji_increment_mid(client->mid);
01402       iks_send(client->p, iq);
01403    } else 
01404       ast_log(LOG_ERROR, "Out of memory.\n");
01405    return res;
01406 }

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1853 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().

01854 {
01855    if (client) {
01856       if (option_verbose > 3)
01857          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n");
01858       iks_disconnect(client->p);
01859       iks_parser_delete(client->p);
01860       ASTOBJ_UNREF(client, aji_client_destroy);
01861    }
01862 
01863    return 1;
01864 }

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 2292 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().

02293 {
02294    struct aji_client *client = NULL;
02295 
02296    client = ASTOBJ_CONTAINER_FIND(&clients, name);
02297    if (!client && !strchr(name, '@'))
02298       client = ASTOBJ_CONTAINER_FIND_FULL(&clients, name, user,,, strcasecmp);
02299    return client;
02300 }

struct aji_client_container* ast_aji_get_clients ( void   ) 

Definition at line 2302 of file res_jabber.c.

References clients.

02303 {
02304    return &clients;
02305 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

Definition at line 1514 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().

01515 {
01516    int i = 0;
01517 
01518    for (i = strlen(mid) - 1; i >= 0; i--) {
01519       if (mid[i] != 'z') {
01520          mid[i] = mid[i] + 1;
01521          i = 0;
01522       } else
01523          mid[i] = 'a';
01524    }
01525 }

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 1441 of file res_jabber.c.

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

01442 {
01443    int res = 0;
01444    iks *invite, *body, *namespace;
01445 
01446    invite = iks_new("message");
01447    body = iks_new("body");
01448    namespace = iks_new("x");
01449    if (client && invite && body && namespace) {
01450       iks_insert_attrib(invite, "to", user);
01451       iks_insert_attrib(invite, "id", client->mid);
01452       ast_aji_increment_mid(client->mid);
01453       iks_insert_cdata(body, message, 0);
01454       iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
01455       iks_insert_attrib(namespace, "jid", room);
01456       iks_insert_node(invite, body);
01457       iks_insert_node(invite, namespace);
01458       res = iks_send(client->p, invite);
01459    } else 
01460       ast_log(LOG_ERROR, "Out of memory.\n");
01461    if (body)
01462       iks_delete(body);
01463    if (namespace)
01464       iks_delete(namespace);
01465    if (invite)
01466       iks_delete(invite);
01467    return res;
01468 }

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1413 of file res_jabber.c.

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

01414 {
01415    int res = 0;
01416    iks *presence = NULL, *priority = NULL;
01417    presence = iks_new("presence");
01418    priority = iks_new("priority");
01419    if (presence && priority && client) {
01420       iks_insert_cdata(priority, "0", 1);
01421       iks_insert_attrib(presence, "to", room);
01422       iks_insert_node(presence, priority);
01423       res = iks_send(client->p, presence);
01424       iks_insert_cdata(priority, "5", 1);
01425       iks_insert_attrib(presence, "to", room);
01426       res = iks_send(client->p, presence);
01427    } else 
01428       ast_log(LOG_ERROR, "Out of memory.\n");
01429    if (presence)
01430       iks_delete(presence);
01431    if (priority)
01432       iks_delete(priority);
01433    return res;
01434 }

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 1368 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().

01369 {
01370    int res = 0;
01371    iks *message_packet = NULL;
01372    if (client->state == AJI_CONNECTED) {
01373       message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message);
01374       if (message_packet) {
01375          iks_insert_attrib(message_packet, "from", client->jid->full);
01376          res = iks_send(client->p, message_packet);
01377       } else {
01378          ast_log(LOG_ERROR, "Out of memory.\n");
01379       }
01380       if (message_packet)
01381          iks_delete(message_packet);
01382    } else
01383       ast_log(LOG_WARNING, "JABBER: Not connected can't send\n");
01384    return 1;
01385 }

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 283 of file res_jabber.c.

Referenced by aji_handle_presence().

00284 {
00285    if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps"))
00286       return 1;
00287    return 0;
00288 }

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

Definition at line 307 of file res_jabber.c.

References ast_sha1_hash().

Referenced by aji_act_hook().

00308 {
00309    iks *x, *y;
00310    x = iks_new("iq");
00311    iks_insert_attrib(x, "type", "set");
00312    y = iks_insert(x, "query");
00313    iks_insert_attrib(y, "xmlns", IKS_NS_AUTH);
00314    iks_insert_cdata(iks_insert(y, "username"), id->user, 0);
00315    iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0);
00316    if (sid) {
00317       char buf[41];
00318       char sidpass[100];
00319       snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass);
00320       ast_sha1_hash(buf, sidpass);
00321       iks_insert_cdata(iks_insert(y, "digest"), buf, 0);
00322    } else {
00323       iks_insert_cdata(iks_insert(y, "password"), pass, 0);
00324    }
00325    return x;
00326 }

static int load_module ( void   )  [static]

Definition at line 2400 of file res_jabber.c.

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

02401 {
02402    ASTOBJ_CONTAINER_INIT(&clients);
02403    if(!aji_reload())
02404       return AST_MODULE_LOAD_DECLINE;
02405    ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send,
02406          "Sends a message to a Jabber Client", mandescr_jabber_send);
02407    ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip);
02408    ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip);
02409    ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02410 
02411    ast_log(LOG_NOTICE, "res_jabber.so loaded.\n");
02412    return 0;
02413 }

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 2315 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().

02316 {
02317    struct aji_client *client = NULL;
02318    const char *id = astman_get_header(m,"ActionID");
02319    const char *jabber = astman_get_header(m,"Jabber");
02320    const char *screenname = astman_get_header(m,"ScreenName");
02321    const char *message = astman_get_header(m,"Message");
02322 
02323    if (ast_strlen_zero(jabber)) {
02324       astman_send_error(s, m, "No transport specified");
02325       return 0;
02326    }
02327    if (ast_strlen_zero(screenname)) {
02328       astman_send_error(s, m, "No ScreenName specified");
02329       return 0;
02330    }
02331    if (ast_strlen_zero(message)) {
02332       astman_send_error(s, m, "No Message specified");
02333       return 0;
02334    }
02335 
02336    astman_send_ack(s, m, "Attempting to send Jabber Message");
02337    client = ast_aji_get_client(jabber);
02338    if (!client) {
02339       astman_send_error(s, m, "Could not find Sender");
02340       return 0;
02341    }  
02342    if (strchr(screenname, '@') && message){
02343       ast_aji_send(client, screenname, message);   
02344       if (!ast_strlen_zero(id))
02345          astman_append(s, "ActionID: %s\r\n",id);
02346       astman_append(s, "Response: Success\r\n");
02347       return 0;
02348    }
02349    if (!ast_strlen_zero(id))
02350       astman_append(s, "ActionID: %s\r\n",id);
02351    astman_append(s, "Response: Failure\r\n");
02352    return 0;
02353 }

static int reload ( void   )  [static]

Definition at line 2415 of file res_jabber.c.

References aji_reload().

02416 {
02417    aji_reload();
02418    return 0;
02419 }

static int unload_module ( void   )  [static]

Definition at line 2377 of file res_jabber.c.

References aji_cli, aji_client_destroy(), AJI_DISCONNECTED, ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_log(), ast_manager_unregister(), ast_unregister_application(), ast_verbose(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, clients, LOG_NOTICE, option_verbose, and VERBOSE_PREFIX_3.

02378 {
02379    ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02380    ast_unregister_application(app_ajisend);
02381    ast_unregister_application(app_ajistatus);
02382    ast_manager_unregister("JabberSend");
02383    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02384       ASTOBJ_RDLOCK(iterator);
02385       if (option_verbose > 2)
02386          ast_verbose(VERBOSE_PREFIX_3 "JABBER: %s\n", iterator->name);
02387       iterator->state = AJI_DISCONNECTED;
02388       ast_aji_disconnect(iterator);
02389       pthread_join(iterator->thread, NULL);
02390       ASTOBJ_UNLOCK(iterator);
02391    });
02392 
02393    ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy);
02394    ASTOBJ_CONTAINER_DESTROY(&clients);
02395 
02396    ast_log(LOG_NOTICE, "res_jabber unloaded.\n");
02397    return 0;
02398 }


Variable Documentation

struct ast_cli_entry aji_cli[] [static]

Definition at line 117 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 143 of file res_jabber.c.

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

Definition at line 141 of file res_jabber.c.

char* ajistatus_descrip [static]

Definition at line 153 of file res_jabber.c.

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

Definition at line 151 of file res_jabber.c.

char* app_ajisend = "JabberSend" [static]

Definition at line 139 of file res_jabber.c.

char* app_ajistatus = "JabberStatus" [static]

Definition at line 149 of file res_jabber.c.

struct aji_capabilities* capabilities

Definition at line 163 of file res_jabber.c.

Referenced by aji_find_version(), and ast_request().

struct aji_client_container clients

Definition at line 161 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 100 of file res_jabber.c.

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

Global flags, initialized to default values.

Definition at line 166 of file res_jabber.c.

char mandescr_jabber_send[] [static]

Definition at line 2307 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 104 of file res_jabber.c.

char reload_usage[] [static]

Initial value:

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

Definition at line 108 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 112 of file res_jabber.c.


Generated on Mon Apr 30 07:46:12 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1