Mon May 14 04:50:50 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)
 Find version in XML stream and populate our capabilities list.
static int aji_get_roster (struct aji_client *client)
static void aji_handle_iq (struct aji_client *client, iks *node)
 Handles <iq> tags.
static void aji_handle_message (struct aji_client *client, ikspak *pak)
 Handles presence packets.
static void aji_handle_presence (struct aji_client *client, ikspak *pak)
static void aji_handle_subscribe (struct aji_client *client, ikspak *pak)
 handles subscription requests.
static int aji_highest_bit (int number)
 Detects the highest bit in a number.
static int aji_load_config (void)
 load config file.
static void aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming)
 the debug loop.
static int aji_no_debug (int fd, int argc, char *argv[])
 turnoff console debugging.
static void aji_pruneregister (struct aji_client *client)
 attempts to register to a transport. attempts to register to a transport step 2. goes through roster and prunes users not needed in list, or adds them accordingly.
static int aji_reconnect (struct aji_client *client)
static void * aji_recv_loop (void *data)
 receive message loop.
static int aji_register_approve_handler (void *data, ikspak *pak)
static int aji_register_query_handler (void *data, ikspak *pak)
static int aji_reload (void)
static int aji_send_exec (struct ast_channel *chan, void *data)
 Dial plan function to send a message.
static void aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc)
 set presence of client.
static int aji_show_clients (int fd, int argc, char *argv[])
 show client status.
static int aji_status_exec (struct ast_channel *chan, void *data)
 Dial plan function status(). puts the status of watched user into a channel variable.
static int aji_test (int fd, int argc, char *argv[])
 send test message for debugging.
int ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic)
 create a chatroom.
int ast_aji_disconnect (struct aji_client *client)
 disconnect from jabber server.
aji_clientast_aji_get_client (const char *name)
 grab a aji_client structure by label name.
aji_client_containerast_aji_get_clients (void)
void ast_aji_increment_mid (char *mid)
 increments the mid field for messages and other events.
int ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message)
 invite to a chatroom.
int ast_aji_join_chat (struct aji_client *client, char *room)
 join a chatroom.
int ast_aji_send (struct aji_client *client, const char *address, const char *message)
 sends messages.
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"AJI - Asterisk Jabber Interface",.load=load_module,.unload=unload_module,.reload=reload,)
static int gtalk_yuck (iks *node)
static iks * jabber_make_auth (iksid *id, const char *pass, const char *sid)
static int load_module (void)
static int manager_jabber_send (struct mansession *s, const struct message *m)
 Send a Jabber Message via call from the Manager.
static int reload (void)
static int unload_module (void)

Variables

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


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

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

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

01798 {
01799    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01800    int res = 0;
01801 
01802    if (client) {
01803       if (client->state == AJI_DISCONNECTED) {
01804          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);
01805          client->state = AJI_CONNECTING;
01806          client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
01807          iks_filter_remove_hook(client->f, aji_client_connect);
01808          if(!client->component) /*client*/
01809             aji_get_roster(client);
01810       }
01811    } else
01812       ast_log(LOG_ERROR, "Out of memory.\n");
01813 
01814    ASTOBJ_UNREF(client, aji_client_destroy);
01815    return res;
01816 }

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

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

static int aji_client_initialize ( struct aji_client client  )  [static]

prepares client for connect.

Parameters:
aji_client struct.
Returns:
1.

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

01824 {
01825    int connected = 0;
01826 
01827    connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server);
01828 
01829    if (connected == IKS_NET_NOCONN) {
01830       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01831       return IKS_HOOK;
01832    } else   if (connected == IKS_NET_NODNS) {
01833       ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01834       return IKS_HOOK;
01835    } else
01836       iks_recv(client->p, 30);
01837    return IKS_OK;
01838 }

static int aji_component_initialize ( struct aji_client client  )  [static]

prepares component for connect.

Parameters:
aji_client struct.
Returns:
1.

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

01846 {
01847    int connected = 1;
01848    connected = iks_connect_via(client->p, client->jid->server, client->port, client->user);
01849    if (connected == IKS_NET_NOCONN) {
01850       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01851       return IKS_HOOK;
01852    } else if (connected == IKS_NET_NODNS) {
01853       ast_log(LOG_ERROR, "JABBER ERROR: No DNS\n");
01854       return IKS_HOOK;
01855    } else if (!connected) 
01856       iks_recv(client->p, 30);
01857    return IKS_OK;
01858 }

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

02235 {
02236    struct aji_buddy *buddy = NULL;
02237    int flag = 0;
02238    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
02239    if (!buddy) {
02240       flag = 1;
02241       buddy = malloc(sizeof(struct aji_buddy));
02242       if(!buddy) {
02243          ast_log(LOG_WARNING, "Out of memory\n");
02244          return 0;
02245       }
02246       memset(buddy, 0, sizeof(struct aji_buddy));
02247       ASTOBJ_INIT(buddy);
02248    }
02249    ASTOBJ_WRLOCK(buddy);
02250    ast_copy_string(buddy->name, label, sizeof(buddy->name));
02251    ASTOBJ_UNLOCK(buddy);
02252    if(flag)
02253       ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
02254    else {
02255       ASTOBJ_UNMARK(buddy);
02256       ASTOBJ_UNREF(buddy, aji_buddy_destroy);
02257    }
02258    return 1;
02259 }

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

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

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

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

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

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

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

00782 {
00783    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00784    char *node = NULL;
00785 
00786    if (!(node = iks_find_attrib(pak->query, "node"))) {
00787       iks *iq = NULL, *query = NULL, *item = NULL;
00788       iq = iks_new("iq");
00789       query = iks_new("query");
00790       item = iks_new("item");
00791 
00792       if (iq && query && item) {
00793          iks_insert_attrib(iq, "from", client->user);
00794          iks_insert_attrib(iq, "to", pak->from->full);
00795          iks_insert_attrib(iq, "id", pak->id);
00796          iks_insert_attrib(iq, "type", "result");
00797          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00798          iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
00799          iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands");
00800          iks_insert_attrib(item, "jid", client->user);
00801 
00802          iks_insert_node(iq, query);
00803          iks_insert_node(query, item);
00804          iks_send(client->p, iq);
00805       } else {
00806          ast_log(LOG_ERROR, "Out of memory.\n");
00807       }
00808       if (iq)
00809          iks_delete(iq);
00810       if (query)
00811          iks_delete(query);
00812       if (item)
00813          iks_delete(item);
00814 
00815    } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
00816       iks *iq, *query, *confirm;
00817       iq = iks_new("iq");
00818       query = iks_new("query");
00819       confirm = iks_new("item");
00820       if (iq && query && confirm && client) {
00821          iks_insert_attrib(iq, "from", client->user);
00822          iks_insert_attrib(iq, "to", pak->from->full);
00823          iks_insert_attrib(iq, "id", pak->id);
00824          iks_insert_attrib(iq, "type", "result");
00825          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00826          iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
00827          iks_insert_attrib(confirm, "node", "confirmaccount");
00828          iks_insert_attrib(confirm, "name", "Confirm AIM account");
00829          iks_insert_attrib(confirm, "jid", "blog.astjab.org");
00830 
00831          iks_insert_node(iq, query);
00832          iks_insert_node(query, confirm);
00833          iks_send(client->p, iq);
00834       } else {
00835          ast_log(LOG_ERROR, "Out of memory.\n");
00836       }
00837       if (iq)
00838          iks_delete(iq);
00839       if (query)
00840          iks_delete(query);
00841       if (confirm)
00842          iks_delete(confirm);
00843 
00844    } else if (!strcasecmp(node, "confirmaccount")) {
00845       iks *iq = NULL, *query = NULL, *feature = NULL;
00846 
00847       iq = iks_new("iq");
00848       query = iks_new("query");
00849       feature = iks_new("feature");
00850 
00851       if (iq && query && feature && client) {
00852          iks_insert_attrib(iq, "from", client->user);
00853          iks_insert_attrib(iq, "to", pak->from->full);
00854          iks_insert_attrib(iq, "id", pak->id);
00855          iks_insert_attrib(iq, "type", "result");
00856          iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
00857          iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands");
00858          iks_insert_node(iq, query);
00859          iks_insert_node(query, feature);
00860          iks_send(client->p, iq);
00861       } else {
00862          ast_log(LOG_ERROR, "Out of memory.\n");
00863       }
00864       if (iq)
00865          iks_delete(iq);
00866       if (query)
00867          iks_delete(query);
00868       if (feature)
00869          iks_delete(feature);
00870    }
00871 
00872    ASTOBJ_UNREF(client, aji_client_destroy);
00873    return IKS_FILTER_EAT;
00874 
00875 }

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

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

01916 {
01917    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01918       ASTOBJ_RDLOCK(iterator); 
01919       iterator->debug = 1;
01920       ASTOBJ_UNLOCK(iterator);
01921    });
01922    ast_cli(fd, "Jabber Debugging Enabled.\n");
01923    return RESULT_SUCCESS;
01924 }

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

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

01932 {
01933    aji_reload();
01934    ast_cli(fd, "Jabber Reloaded.\n");
01935    return RESULT_SUCCESS;
01936 }

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

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

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

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

00281 {
00282    struct aji_resource *res = NULL;
00283    if (!buddy || !name)
00284       return res;
00285    res = buddy->resources;
00286    while (res) {
00287       if (!strcasecmp(res->resource, name)) {
00288          break;
00289       }
00290       res = res->next;
00291    }
00292    return res;
00293 }

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

Find version in XML stream and populate our capabilities list.

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

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

00220 {
00221    struct aji_capabilities *list = NULL;
00222    struct aji_version *res = NULL;
00223 
00224    list = capabilities;
00225 
00226    if(!node)
00227       node = pak->from->full;
00228    if(!version)
00229       version = "none supplied.";
00230    while(list) {
00231       if(!strcasecmp(list->node, node)) {
00232          res = list->versions;
00233          while(res) {
00234              if(!strcasecmp(res->version, version))
00235                 return res;
00236              res = res->next;
00237          }
00238          /* Specified version not found. Let's add it to 
00239             this node in our capabilities list */
00240          if(!res) {
00241             res = (struct aji_version *)malloc(sizeof(struct aji_version));
00242             if(!res) {
00243                ast_log(LOG_ERROR, "Out of memory!\n");
00244                return NULL;
00245             }
00246             res->jingle = 0;
00247             res->parent = list;
00248             ast_copy_string(res->version, version, sizeof(res->version));
00249             res->next = list->versions;
00250             list->versions = res;
00251             return res;
00252          }
00253       }
00254       list = list->next;
00255    }
00256    /* Specified node not found. Let's add it our capabilities list */
00257    if(!list) {
00258       list = (struct aji_capabilities *)malloc(sizeof(struct aji_capabilities));
00259       if(!list) {
00260          ast_log(LOG_ERROR, "Out of memory!\n");
00261          return NULL;
00262       }
00263       res = (struct aji_version *)malloc(sizeof(struct aji_version));
00264       if(!res) {
00265          ast_log(LOG_ERROR, "Out of memory!\n");
00266          return NULL;
00267       }
00268       ast_copy_string(list->node, node, sizeof(list->node));
00269       ast_copy_string(res->version, version, sizeof(res->version));
00270       res->jingle = 0;
00271       res->parent = list;
00272       res->next = NULL;
00273       list->versions = res;
00274       list->next = capabilities;
00275       capabilities = list;
00276    }
00277    return res;
00278 }

static int aji_get_roster ( struct aji_client client  )  [static]

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

01779 {
01780    iks *roster = NULL;
01781    roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
01782    if(roster) {
01783       iks_insert_attrib(roster, "id", "roster");
01784       aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
01785       iks_send(client->p, roster);
01786    }
01787    if (roster)
01788       iks_delete(roster);
01789    return 1;
01790 }

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

Referenced by aji_act_hook().

01091 {
01092    /*Nothing to see here */
01093 }

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

01101 {
01102    struct aji_message *insert, *tmp;
01103    int flag = 0;
01104    
01105    if (!(insert = ast_calloc(1, sizeof(struct aji_message))))
01106       return;
01107    time(&insert->arrived);
01108    if (iks_find_cdata(pak->x, "body"))
01109       insert->message = ast_strdup(iks_find_cdata(pak->x, "body"));
01110    if(pak->id)
01111       ast_copy_string(insert->id, pak->id, sizeof(insert->message));
01112    if (pak->from)
01113       insert->from = ast_strdup(pak->from->full);
01114    AST_LIST_LOCK(&client->messages);
01115    AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) {
01116       if (flag) {
01117          AST_LIST_REMOVE_CURRENT(&client->messages, list);
01118          if (tmp->from)
01119             free(tmp->from);
01120          if (tmp->message)
01121             free(tmp->message);
01122       } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) {
01123          flag = 1;
01124          AST_LIST_REMOVE_CURRENT(&client->messages, list);
01125          if (tmp->from)
01126             free(tmp->from);
01127          if (tmp->message)
01128             free(tmp->message);
01129       }
01130    }
01131    AST_LIST_TRAVERSE_SAFE_END;
01132    AST_LIST_INSERT_HEAD(&client->messages, insert, list);
01133    AST_LIST_UNLOCK(&client->messages);
01134 }

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

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

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

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

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

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

Referenced by aji_act_hook().

00308 {
00309    int x = sizeof(number) * 8 - 1;
00310    if (!number)
00311       return 0;
00312    for (; x > 0; x--) {
00313       if (number & (1 << x))
00314          break;
00315    }
00316    return (1 << x);
00317 }

static int aji_load_config ( void   )  [static]

load config file.

Parameters:
void. 
Returns:
1.

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

02267 {
02268    char *cat = NULL;
02269    int debug = 1;
02270    struct ast_config *cfg = NULL;
02271    struct ast_variable *var = NULL;
02272 
02273    cfg = ast_config_load(JABBER_CONFIG);
02274    if (!cfg) {
02275       ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
02276       return 0;
02277    }
02278 
02279    cat = ast_category_browse(cfg, NULL);
02280    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02281       if (!strcasecmp(var->name, "debug"))
02282          debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1;
02283       else if (!strcasecmp(var->name, "autoprune"))
02284          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE);
02285       else if (!strcasecmp(var->name, "autoregister"))
02286          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER);
02287    }
02288 
02289    while (cat) {
02290       if (strcasecmp(cat, "general")) {
02291             var = ast_variable_browse(cfg, cat);
02292             aji_create_client(cat, var, debug);
02293       }
02294       cat = ast_category_browse(cfg, cat);
02295    }
02296    return 1;
02297 }

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

00447 {
00448    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00449    manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp);
00450 
00451    if (client->debug) {
00452       if (is_incoming)
00453          ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp);
00454       else {
00455          if( strlen(xmpp) == 1) {
00456             if(option_debug > 2  && xmpp[0] == ' ')
00457             ast_verbose("\nJABBER: Keep alive packet\n");
00458          } else
00459             ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp);
00460       }
00461 
00462    }
00463    ASTOBJ_UNREF(client, aji_client_destroy);
00464 }

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

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

01944 {
01945    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01946       ASTOBJ_RDLOCK(iterator);
01947       iterator->debug = 0;
01948       ASTOBJ_UNLOCK(iterator);
01949    });
01950    ast_cli(fd, "Jabber Debugging Disabled.\n");
01951    return RESULT_SUCCESS;
01952 }

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

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

static int aji_reconnect ( struct aji_client client  )  [static]

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

01759 {
01760    int res = 0;
01761 
01762    if (client->state)
01763       client->state = AJI_DISCONNECTED;
01764    client->timeout=50;
01765    if (client->p)
01766       iks_parser_reset(client->p);
01767    if (client->authorized)
01768       client->authorized = 0;
01769 
01770    if(client->component)
01771       res = aji_component_initialize(client);
01772    else
01773       res = aji_client_initialize(client);
01774 
01775    return res;
01776 }

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

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

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

01489 {
01490    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01491    int res = IKS_HOOK;
01492    do {
01493       if (res != IKS_OK) {
01494          while(res != IKS_OK) {
01495             if(option_verbose > 3)
01496                ast_verbose("JABBER: reconnecting.\n");
01497             res = aji_reconnect(client);
01498             sleep(4);
01499          }
01500       }
01501 
01502       res = iks_recv(client->p, 1);
01503       client->timeout--;
01504       if (res == IKS_HOOK) 
01505          ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
01506       else if (res == IKS_NET_TLSFAIL)
01507          ast_log(LOG_WARNING, "JABBER:  Failure in TLS.\n");
01508       else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
01509          res = iks_send_raw(client->p, " ");
01510          if(res == IKS_OK)
01511             client->timeout = 50;
01512          else
01513             ast_log(LOG_WARNING, "JABBER:  Network Timeout\n");
01514       } else if (res == IKS_NET_RWERR)
01515          ast_log(LOG_WARNING, "JABBER: socket read error\n");
01516    } while (client);
01517    ASTOBJ_UNREF(client, aji_client_destroy);
01518    return 0;
01519 }

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

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

00673 {
00674    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00675    iks *iq = NULL, *presence = NULL, *x = NULL;
00676 
00677    iq = iks_new("iq");
00678    presence = iks_new("presence");
00679    x = iks_new("x");
00680    if (client && iq && presence && x) {
00681       if (!iks_find(pak->query, "remove")) {
00682          iks_insert_attrib(iq, "from", client->jid->full);
00683          iks_insert_attrib(iq, "to", pak->from->full);
00684          iks_insert_attrib(iq, "id", pak->id);
00685          iks_insert_attrib(iq, "type", "result");
00686          iks_send(client->p, iq);
00687 
00688          iks_insert_attrib(presence, "from", client->jid->full);
00689          iks_insert_attrib(presence, "to", pak->from->partial);
00690          iks_insert_attrib(presence, "id", client->mid);
00691          ast_aji_increment_mid(client->mid);
00692          iks_insert_attrib(presence, "type", "subscribe");
00693          iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
00694          iks_insert_node(presence, x);
00695          iks_send(client->p, presence); 
00696       }
00697    } else {
00698       ast_log(LOG_ERROR, "Out of memory.\n");
00699    }
00700 
00701    if (iq)
00702       iks_delete(iq);
00703    if(presence)
00704       iks_delete(presence);
00705    if (x)
00706       iks_delete(x);
00707    ASTOBJ_UNREF(client, aji_client_destroy);
00708    return IKS_FILTER_EAT;
00709 }

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

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

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

static int aji_reload ( void   )  [static]

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

02369 {
02370    ASTOBJ_CONTAINER_MARKALL(&clients);
02371    if (!aji_load_config()) {
02372       ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
02373       return 0;
02374    }
02375    ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
02376    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02377       ASTOBJ_RDLOCK(iterator);
02378       if(iterator->state == AJI_DISCONNECTED) {
02379          if (!iterator->thread)
02380             ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
02381       } else if (iterator->state == AJI_CONNECTING)
02382          aji_get_roster(iterator);
02383       ASTOBJ_UNLOCK(iterator);
02384    });
02385    
02386    return 1;
02387 }

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

00411 {
00412    struct aji_client *client = NULL;
00413 
00414    char *s = NULL, *sender = NULL, *recipient = NULL, *message = NULL;
00415 
00416    if (!data) {
00417       ast_log(LOG_ERROR, "This application requires arguments.\n");
00418       return 0;
00419    }
00420    s = ast_strdupa(data);
00421    if (s) {
00422       sender = strsep(&s, "|");
00423       if (sender && (sender[0] != '\0')) {
00424          recipient = strsep(&s, "|");
00425          if (recipient && (recipient[0] != '\0')) {
00426             message = s;
00427          } else {
00428             ast_log(LOG_ERROR, "Bad arguments: %s\n", (char *) data);
00429             return -1;
00430          }
00431       }
00432    }
00433    if (!(client = ast_aji_get_client(sender))) {
00434       ast_log(LOG_WARNING, "Could not find sender connection: %s\n", sender);
00435       return -1;
00436    }
00437    if (strchr(recipient, '@') && message)
00438       ast_aji_send(client, recipient, message);
00439    return 0;
00440 }

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

01884 {
01885    int res = 0;
01886    iks *presence = iks_make_pres(level, desc);
01887    iks *cnode = iks_new("c");
01888    iks *priority = iks_new("priority");
01889 
01890    iks_insert_cdata(priority, "0", 1);
01891    if (presence && cnode && client) {
01892       if(to)
01893          iks_insert_attrib(presence, "to", to);
01894       if(from)
01895          iks_insert_attrib(presence, "from", from);
01896       iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
01897       iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
01898       iks_insert_attrib(cnode, "ext", "voice-v1");
01899       iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
01900       iks_insert_node(presence, cnode);
01901       res = iks_send(client->p, presence);
01902    } else
01903       ast_log(LOG_ERROR, "Out of memory.\n");
01904    if (cnode)
01905       iks_delete(cnode);
01906    if (presence)
01907       iks_delete(presence);
01908 }

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

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

01960 {
01961    char *status;
01962    int count = 0;
01963    ast_cli(fd, "Jabber Users and their status:\n");
01964    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01965       ASTOBJ_RDLOCK(iterator);
01966       count++;
01967       switch (iterator->state) {
01968       case AJI_DISCONNECTED:
01969          status = "Disconnected";
01970          break;
01971       case AJI_CONNECTING:
01972          status = "Connecting";
01973          break;
01974       case AJI_CONNECTED:
01975          status = "Connected";
01976          break;
01977       default:
01978          status = "Unknown";
01979       }
01980       ast_cli(fd, "       User: %s     - %s\n", iterator->user, status);
01981       ASTOBJ_UNLOCK(iterator);
01982    });
01983    ast_cli(fd, "----\n");
01984    ast_cli(fd, "   Number of users: %d\n", count);
01985    return RESULT_SUCCESS;
01986 }

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

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

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

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

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

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

01405 {
01406    int res = 0;
01407    iks *iq = NULL;
01408    iq = iks_new("iq");
01409    if (iq && client) {
01410       iks_insert_attrib(iq, "type", "get");
01411       iks_insert_attrib(iq, "to", server);
01412       iks_insert_attrib(iq, "id", client->mid);
01413       ast_aji_increment_mid(client->mid);
01414       iks_send(client->p, iq);
01415    } else 
01416       ast_log(LOG_ERROR, "Out of memory.\n");
01417    return res;
01418 }

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

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

01866 {
01867    if (client) {
01868       if (option_verbose > 3)
01869          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n");
01870       iks_disconnect(client->p);
01871       iks_parser_delete(client->p);
01872       ASTOBJ_UNREF(client, aji_client_destroy);
01873    }
01874 
01875    return 1;
01876 }

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

02305 {
02306    struct aji_client *client = NULL;
02307 
02308    client = ASTOBJ_CONTAINER_FIND(&clients, name);
02309    if (!client && !strchr(name, '@'))
02310       client = ASTOBJ_CONTAINER_FIND_FULL(&clients, name, user,,, strcasecmp);
02311    return client;
02312 }

struct aji_client_container* ast_aji_get_clients ( void   ) 

Definition at line 2314 of file res_jabber.c.

References clients.

02315 {
02316    return &clients;
02317 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

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

01527 {
01528    int i = 0;
01529 
01530    for (i = strlen(mid) - 1; i >= 0; i--) {
01531       if (mid[i] != 'z') {
01532          mid[i] = mid[i] + 1;
01533          i = 0;
01534       } else
01535          mid[i] = 'a';
01536    }
01537 }

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

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

01454 {
01455    int res = 0;
01456    iks *invite, *body, *namespace;
01457 
01458    invite = iks_new("message");
01459    body = iks_new("body");
01460    namespace = iks_new("x");
01461    if (client && invite && body && namespace) {
01462       iks_insert_attrib(invite, "to", user);
01463       iks_insert_attrib(invite, "id", client->mid);
01464       ast_aji_increment_mid(client->mid);
01465       iks_insert_cdata(body, message, 0);
01466       iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
01467       iks_insert_attrib(namespace, "jid", room);
01468       iks_insert_node(invite, body);
01469       iks_insert_node(invite, namespace);
01470       res = iks_send(client->p, invite);
01471    } else 
01472       ast_log(LOG_ERROR, "Out of memory.\n");
01473    if (body)
01474       iks_delete(body);
01475    if (namespace)
01476       iks_delete(namespace);
01477    if (invite)
01478       iks_delete(invite);
01479    return res;
01480 }

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1425 of file res_jabber.c.

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

01426 {
01427    int res = 0;
01428    iks *presence = NULL, *priority = NULL;
01429    presence = iks_new("presence");
01430    priority = iks_new("priority");
01431    if (presence && priority && client) {
01432       iks_insert_cdata(priority, "0", 1);
01433       iks_insert_attrib(presence, "to", room);
01434       iks_insert_node(presence, priority);
01435       res = iks_send(client->p, presence);
01436       iks_insert_cdata(priority, "5", 1);
01437       iks_insert_attrib(presence, "to", room);
01438       res = iks_send(client->p, presence);
01439    } else 
01440       ast_log(LOG_ERROR, "Out of memory.\n");
01441    if (presence)
01442       iks_delete(presence);
01443    if (priority)
01444       iks_delete(priority);
01445    return res;
01446 }

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

01381 {
01382    int res = 0;
01383    iks *message_packet = NULL;
01384    if (client->state == AJI_CONNECTED) {
01385       message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message);
01386       if (message_packet) {
01387          iks_insert_attrib(message_packet, "from", client->jid->full);
01388          res = iks_send(client->p, message_packet);
01389       } else {
01390          ast_log(LOG_ERROR, "Out of memory.\n");
01391       }
01392       if (message_packet)
01393          iks_delete(message_packet);
01394    } else
01395       ast_log(LOG_WARNING, "JABBER: Not connected can't send\n");
01396    return 1;
01397 }

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

Referenced by aji_handle_presence().

00296 {
00297    if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps"))
00298       return 1;
00299    return 0;
00300 }

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

Definition at line 319 of file res_jabber.c.

References ast_sha1_hash().

Referenced by aji_act_hook().

00320 {
00321    iks *x, *y;
00322    x = iks_new("iq");
00323    iks_insert_attrib(x, "type", "set");
00324    y = iks_insert(x, "query");
00325    iks_insert_attrib(y, "xmlns", IKS_NS_AUTH);
00326    iks_insert_cdata(iks_insert(y, "username"), id->user, 0);
00327    iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0);
00328    if (sid) {
00329       char buf[41];
00330       char sidpass[100];
00331       snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass);
00332       ast_sha1_hash(buf, sidpass);
00333       iks_insert_cdata(iks_insert(y, "digest"), buf, 0);
00334    } else {
00335       iks_insert_cdata(iks_insert(y, "password"), pass, 0);
00336    }
00337    return x;
00338 }

static int load_module ( void   )  [static]

Definition at line 2412 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.

02413 {
02414    ASTOBJ_CONTAINER_INIT(&clients);
02415    if(!aji_reload())
02416       return AST_MODULE_LOAD_DECLINE;
02417    ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send,
02418          "Sends a message to a Jabber Client", mandescr_jabber_send);
02419    ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip);
02420    ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip);
02421    ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02422 
02423    ast_log(LOG_NOTICE, "res_jabber.so loaded.\n");
02424    return 0;
02425 }

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

02328 {
02329    struct aji_client *client = NULL;
02330    const char *id = astman_get_header(m,"ActionID");
02331    const char *jabber = astman_get_header(m,"Jabber");
02332    const char *screenname = astman_get_header(m,"ScreenName");
02333    const char *message = astman_get_header(m,"Message");
02334 
02335    if (ast_strlen_zero(jabber)) {
02336       astman_send_error(s, m, "No transport specified");
02337       return 0;
02338    }
02339    if (ast_strlen_zero(screenname)) {
02340       astman_send_error(s, m, "No ScreenName specified");
02341       return 0;
02342    }
02343    if (ast_strlen_zero(message)) {
02344       astman_send_error(s, m, "No Message specified");
02345       return 0;
02346    }
02347 
02348    astman_send_ack(s, m, "Attempting to send Jabber Message");
02349    client = ast_aji_get_client(jabber);
02350    if (!client) {
02351       astman_send_error(s, m, "Could not find Sender");
02352       return 0;
02353    }  
02354    if (strchr(screenname, '@') && message){
02355       ast_aji_send(client, screenname, message);   
02356       if (!ast_strlen_zero(id))
02357          astman_append(s, "ActionID: %s\r\n",id);
02358       astman_append(s, "Response: Success\r\n");
02359       return 0;
02360    }
02361    if (!ast_strlen_zero(id))
02362       astman_append(s, "ActionID: %s\r\n",id);
02363    astman_append(s, "Response: Failure\r\n");
02364    return 0;
02365 }

static int reload ( void   )  [static]

Definition at line 2427 of file res_jabber.c.

References aji_reload().

02428 {
02429    aji_reload();
02430    return 0;
02431 }

static int unload_module ( void   )  [static]

Definition at line 2389 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.

02390 {
02391    ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02392    ast_unregister_application(app_ajisend);
02393    ast_unregister_application(app_ajistatus);
02394    ast_manager_unregister("JabberSend");
02395    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02396       ASTOBJ_RDLOCK(iterator);
02397       if (option_verbose > 2)
02398          ast_verbose(VERBOSE_PREFIX_3 "JABBER: %s\n", iterator->name);
02399       iterator->state = AJI_DISCONNECTED;
02400       ast_aji_disconnect(iterator);
02401       pthread_join(iterator->thread, NULL);
02402       ASTOBJ_UNLOCK(iterator);
02403    });
02404 
02405    ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy);
02406    ASTOBJ_CONTAINER_DESTROY(&clients);
02407 
02408    ast_log(LOG_NOTICE, "res_jabber unloaded.\n");
02409    return 0;
02410 }


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 = NULL

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 2319 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 May 14 04:50:51 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1