Mon Jul 14 17:25:23 2008

Asterisk developer's documentation


res_jabber.c File Reference

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

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

Include dependency graph for res_jabber.c:

Go to the source code of this file.

Defines

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

Functions

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

Variables

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


Detailed Description

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

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

Definition in file res_jabber.c.


Define Documentation

#define FALSE   0

Definition at line 64 of file res_jabber.c.

#define JABBER_CONFIG   "jabber.conf"

Definition at line 61 of file res_jabber.c.

Referenced by aji_load_config().

#define TRUE   1

Definition at line 68 of file res_jabber.c.


Function Documentation

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

The action hook parses the inbound packets, constantly running.

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

Definition at line 488 of file res_jabber.c.

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

Referenced by aji_create_client().

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

static void aji_buddy_destroy ( struct aji_buddy obj  )  [static]

Deletes the aji_buddy data structure.

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

Definition at line 211 of file res_jabber.c.

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

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

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

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

connects as a client to jabber server.

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

Definition at line 1856 of file res_jabber.c.

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

Referenced by aji_act_hook().

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

static void aji_client_destroy ( struct aji_client obj  )  [static]

Deletes the aji_client data structure.

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

Definition at line 187 of file res_jabber.c.

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

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

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

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

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

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

static int aji_client_initialize ( struct aji_client client  )  [static]

prepares client for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1882 of file res_jabber.c.

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

Referenced by aji_reconnect().

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

static int aji_component_initialize ( struct aji_client client  )  [static]

prepares component for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1904 of file res_jabber.c.

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

Referenced by aji_reconnect().

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

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

creates transport. creates buddy.

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

Definition at line 2295 of file res_jabber.c.

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

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

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

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

creates aji_client structure.

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

Definition at line 2104 of file res_jabber.c.

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

Referenced by aji_load_config().

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

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

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

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

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

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

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

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

turnon console debugging.

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

Definition at line 1975 of file res_jabber.c.

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

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

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

reload jabber module.

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

Definition at line 1991 of file res_jabber.c.

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

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

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

filters the roster packet we get back from server.

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

Definition at line 1745 of file res_jabber.c.

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

Referenced by aji_client_connect().

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

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

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

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

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

Find version in XML stream and populate our capabilities list.

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

Definition at line 233 of file res_jabber.c.

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

Referenced by aji_handle_presence().

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

static int aji_get_roster ( struct aji_client client  )  [static]

Definition at line 1837 of file res_jabber.c.

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

Referenced by aji_client_connect(), and aji_reload().

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

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

Handles <iq> tags.

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

Definition at line 1120 of file res_jabber.c.

Referenced by aji_act_hook().

01121 {
01122    /*Nothing to see here */
01123 }

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

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

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

Definition at line 1166 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(), aji_client::jid, 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().

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

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

References aji_create_buddy(), aji_set_presence(), ast_log(), ast_verbose(), ASTOBJ_CONTAINER_FIND, aji_client::buddies, 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().

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

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

Referenced by aji_act_hook().

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

static int aji_load_config ( void   )  [static]

load config file.

Parameters:
void. 
Returns:
1.

Definition at line 2327 of file res_jabber.c.

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

Referenced by aji_reload().

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

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

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

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

turnoff console debugging.

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

Definition at line 2003 of file res_jabber.c.

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

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

static void aji_pruneregister ( struct aji_client client  )  [static]

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

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1692 of file res_jabber.c.

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

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

static int aji_reconnect ( struct aji_client client  )  [static]

Definition at line 1817 of file res_jabber.c.

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

Referenced by aji_recv_loop().

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

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

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1541 of file res_jabber.c.

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

Referenced by aji_reload().

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

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

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

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

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

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

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

static int aji_reload ( void   )  [static]

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

02444 {
02445    ASTOBJ_CONTAINER_MARKALL(&clients);
02446    if (!aji_load_config()) {
02447       ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
02448       return 0;
02449    }
02450    ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
02451    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02452       ASTOBJ_RDLOCK(iterator);
02453       if(iterator->state == AJI_DISCONNECTED) {
02454          if (!iterator->thread)
02455             ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
02456       } else if (iterator->state == AJI_CONNECTING)
02457          aji_get_roster(iterator);
02458       ASTOBJ_UNLOCK(iterator);
02459    });
02460    
02461    return 1;
02462 }

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

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

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

set presence of client.

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

Definition at line 1943 of file res_jabber.c.

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

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

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

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

show client status.

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

Definition at line 2019 of file res_jabber.c.

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

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

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

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

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

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

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

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

send test message for debugging.

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

Definition at line 2053 of file res_jabber.c.

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

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

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

create a chatroom.

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

Definition at line 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 *iq = NULL;
01457    iq = iks_new("iq");
01458 
01459    if (iq && client) {
01460       iks_insert_attrib(iq, "type", "get");
01461       iks_insert_attrib(iq, "to", server);
01462       iks_insert_attrib(iq, "id", client->mid);
01463       ast_aji_increment_mid(client->mid);
01464       iks_send(client->p, iq);
01465    } else 
01466       ast_log(LOG_ERROR, "Out of memory.\n");
01467 
01468    iks_delete(iq);
01469 
01470    return res;
01471 }

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1925 of file res_jabber.c.

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

Referenced by unload_module().

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

struct aji_client* ast_aji_get_client ( const char *  name  ) 

grab a aji_client structure by label name or JID (without the resource string)

Parameters:
name label or JID
Returns:
aji_client.

Definition at line 2367 of file res_jabber.c.

References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, clients, and strsep().

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

02368 {
02369    struct aji_client *client = NULL;
02370    char *aux = NULL;
02371 
02372    client = ASTOBJ_CONTAINER_FIND(&clients, name);
02373    if (!client && strchr(name, '@')) {
02374       ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02375          aux = ast_strdupa(iterator->user);
02376          if (strchr(aux, '/')) {
02377             /* strip resource for comparison */
02378             aux = strsep(&aux, "/");
02379          }
02380          if (!strncasecmp(aux, name, strlen(aux))) {
02381             client = iterator;
02382          }           
02383       });
02384    }
02385  
02386    return client;
02387 }

struct aji_client_container* ast_aji_get_clients ( void   ) 

Definition at line 2389 of file res_jabber.c.

References clients.

02390 {
02391    return &clients;
02392 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

Definition at line 1585 of file res_jabber.c.

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

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

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

invite to a chatroom.

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

Definition at line 1506 of file res_jabber.c.

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

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

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1478 of file res_jabber.c.

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

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

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

sends messages.

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

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

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

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

Referenced by aji_handle_presence().

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

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

Definition at line 334 of file res_jabber.c.

References ast_sha1_hash().

Referenced by aji_act_hook().

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

static int load_module ( void   )  [static]

Definition at line 2497 of file res_jabber.c.

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

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

Send a Jabber Message via call from the Manager.

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

02403 {
02404    struct aji_client *client = NULL;
02405    const char *id = astman_get_header(m,"ActionID");
02406    const char *jabber = astman_get_header(m,"Jabber");
02407    const char *screenname = astman_get_header(m,"ScreenName");
02408    const char *message = astman_get_header(m,"Message");
02409 
02410    if (ast_strlen_zero(jabber)) {
02411       astman_send_error(s, m, "No transport specified");
02412       return 0;
02413    }
02414    if (ast_strlen_zero(screenname)) {
02415       astman_send_error(s, m, "No ScreenName specified");
02416       return 0;
02417    }
02418    if (ast_strlen_zero(message)) {
02419       astman_send_error(s, m, "No Message specified");
02420       return 0;
02421    }
02422 
02423    astman_send_ack(s, m, "Attempting to send Jabber Message");
02424    client = ast_aji_get_client(jabber);
02425    if (!client) {
02426       astman_send_error(s, m, "Could not find Sender");
02427       return 0;
02428    }  
02429    if (strchr(screenname, '@') && message){
02430       ast_aji_send(client, screenname, message);   
02431       if (!ast_strlen_zero(id))
02432          astman_append(s, "ActionID: %s\r\n",id);
02433       astman_append(s, "Response: Success\r\n");
02434       return 0;
02435    }
02436    if (!ast_strlen_zero(id))
02437       astman_append(s, "ActionID: %s\r\n",id);
02438    astman_append(s, "Response: Failure\r\n");
02439    return 0;
02440 }

static int reload ( void   )  [static]

Definition at line 2511 of file res_jabber.c.

References aji_reload().

02512 {
02513    aji_reload();
02514    return 0;
02515 }

static int unload_module ( void   )  [static]

Definition at line 2464 of file res_jabber.c.

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

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


Variable Documentation

struct ast_cli_entry aji_cli[] [static]

Definition at line 131 of file res_jabber.c.

Referenced by load_module(), and unload_module().

char* ajisend_descrip [static]

Initial value:

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

Definition at line 157 of file res_jabber.c.

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

Definition at line 155 of file res_jabber.c.

char* ajistatus_descrip [static]

Definition at line 167 of file res_jabber.c.

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

Definition at line 165 of file res_jabber.c.

char* app_ajisend = "JabberSend" [static]

Definition at line 153 of file res_jabber.c.

char* app_ajistatus = "JabberStatus" [static]

Definition at line 163 of file res_jabber.c.

struct aji_capabilities* capabilities = NULL

Definition at line 176 of file res_jabber.c.

Referenced by aji_find_version(), and ast_request_with_uniqueid().

struct aji_client_container clients

Definition at line 175 of file res_jabber.c.

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

char debug_usage[] [static]

Initial value:

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

Definition at line 114 of file res_jabber.c.

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

Global flags, initialized to default values.

Definition at line 179 of file res_jabber.c.

char mandescr_jabber_send[] [static]

Definition at line 2394 of file res_jabber.c.

Referenced by load_module().

char no_debug_usage[] [static]

Initial value:

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

Definition at line 118 of file res_jabber.c.

char reload_usage[] [static]

Initial value:

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

Definition at line 122 of file res_jabber.c.

char test_usage[] [static]

Initial value:

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

Definition at line 126 of file res_jabber.c.

int tls_initialized = FALSE [static]

Definition at line 180 of file res_jabber.c.


Generated on Mon Jul 14 17:25:23 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1