Sat Apr 12 07:12:53 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.
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.
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.
struct aji_clientast_aji_get_client (const char *name)
 grab a aji_client structure by label name.
struct 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"
struct aji_capabilitiescapabilities = NULL
struct 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          {
00534             int features = 0;
00535             if (!strcmp("stream:features", iks_name(node))) {
00536                features = iks_stream_features(node);
00537                if (client->usesasl) {
00538                   if (client->usetls && !iks_is_secure(client->p))
00539                      break;
00540                   if (client->authorized) {
00541                      if (features & IKS_STREAM_BIND) {
00542                         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);
00543                         auth = iks_make_resource_bind(client->jid);
00544                         if (auth) {
00545                            iks_insert_attrib(auth, "id", client->mid);
00546                            ast_aji_increment_mid(client->mid);
00547                            iks_send(client->p, auth);
00548                            iks_delete(auth);
00549                         } else {
00550                            ast_log(LOG_ERROR, "Out of memory.\n");
00551                            break;
00552                         }
00553                      }
00554                      if (features & IKS_STREAM_SESSION) {
00555                         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);
00556                         auth = iks_make_session();
00557                         if (auth) {
00558                            iks_insert_attrib(auth, "id", "auth");
00559                            ast_aji_increment_mid(client->mid);
00560                            iks_send(client->p, auth);
00561                            iks_delete(auth);
00562                         } else {
00563                            ast_log(LOG_ERROR, "Out of memory.\n");
00564                         }
00565                      }
00566                   } else {
00567                      if (!client->jid->user) {
00568                         ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full);
00569                         break;
00570                      }
00571                      features = aji_highest_bit(features);
00572                      if (features == IKS_STREAM_SASL_MD5)
00573                         iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, client->jid->user, client->password);
00574                      else {
00575                         if (features == IKS_STREAM_SASL_PLAIN) {
00576                            iks *x = NULL;
00577                            x = iks_new("auth");
00578                            if (x) {
00579                               int len = strlen(client->jid->user) + strlen(client->password) + 3;
00580                               /* XXX Check return values XXX */
00581                               char *s = ast_malloc(80 + len);
00582                               char *base64 = ast_malloc(80 + len * 2);
00583                               iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL);
00584                               iks_insert_attrib(x, "mechanism", "PLAIN");
00585                               sprintf(s, "%c%s%c%s", 0, client->jid->user, 0, client->password);
00586                               ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
00587                               iks_insert_cdata(x, base64, 0);
00588                               iks_send(client->p, x);
00589                               iks_delete(x);
00590                               if (base64)
00591                                  free(base64);
00592                               if (s)
00593                                  free(s);
00594                            } else {
00595                               ast_log(LOG_ERROR, "Out of memory.\n");
00596                            }
00597                         }
00598                      }
00599                   }
00600                }
00601             } else if (!strcmp("failure", iks_name(node))) {
00602                ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
00603             } else if (!strcmp("success", iks_name(node))) {
00604                client->authorized = 1;
00605                iks_send_header(client->p, client->jid->server);
00606             }
00607             break;
00608          }
00609       case IKS_NODE_ERROR: 
00610             ast_log(LOG_ERROR, "JABBER: Node Error\n");
00611             ASTOBJ_UNREF(client, aji_client_destroy);
00612             return IKS_HOOK;
00613             break;
00614       case IKS_NODE_STOP: 
00615             ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00616             ASTOBJ_UNREF(client, aji_client_destroy);
00617             return IKS_HOOK;
00618             break;
00619       }
00620    } else if (client->state != AJI_CONNECTED && client->component) {
00621       switch (type) {
00622       case IKS_NODE_START:
00623          if (client->state == AJI_DISCONNECTED) {
00624             char secret[160], shasum[320], *handshake;
00625 
00626             sprintf(secret, "%s%s", pak->id, client->password);
00627             ast_sha1_hash(shasum, secret);
00628             handshake = NULL;
00629             asprintf(&handshake, "<handshake>%s</handshake>", shasum);
00630             if (handshake) {
00631                iks_send_raw(client->p, handshake);
00632                free(handshake);
00633                handshake = NULL;
00634             }
00635             client->state = AJI_CONNECTING;
00636             if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
00637                client->state = AJI_CONNECTED;
00638             else
00639                ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
00640             break;
00641          }
00642          break;
00643 
00644       case IKS_NODE_NORMAL:
00645          break;
00646 
00647       case IKS_NODE_ERROR:
00648          ast_log(LOG_ERROR, "JABBER: Node Error\n");
00649          ASTOBJ_UNREF(client, aji_client_destroy);
00650          return IKS_HOOK;
00651 
00652       case IKS_NODE_STOP:
00653          ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00654          ASTOBJ_UNREF(client, aji_client_destroy);
00655          return IKS_HOOK;
00656       }
00657    }
00658 
00659    switch (pak->type) {
00660    case IKS_PAK_NONE:
00661       if (option_debug)
00662          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n");
00663       break;
00664    case IKS_PAK_MESSAGE:
00665       aji_handle_message(client, pak);
00666       if (option_debug)
00667          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n");
00668       break;
00669    case IKS_PAK_PRESENCE:
00670       aji_handle_presence(client, pak);
00671       if (option_debug)
00672          ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n");
00673       break;
00674    case IKS_PAK_S10N:
00675       aji_handle_subscribe(client, pak);
00676       if (option_debug)
00677          ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n");
00678       break;
00679    case IKS_PAK_IQ:
00680       if (option_debug)
00681          ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n");
00682       aji_handle_iq(client, node);
00683       break;
00684    default:
00685       if (option_debug)
00686          ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type);
00687       break;
00688    }
00689    
00690    iks_filter_packet(client->f, pak);
00691 
00692    if (node)
00693       iks_delete(node);
00694 
00695    ASTOBJ_UNREF(client, aji_client_destroy);
00696    return IKS_OK;
00697 }

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

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

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.

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

Definition at line 2295 of file res_jabber.c.

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

Referenced by aji_create_client(), and aji_handle_presence().

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

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

creates aji_client structure.

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

Definition at line 2104 of file res_jabber.c.

References aji_act_hook(), AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_destroy(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_copy_flags, ast_false(), AST_FLAGS_ALL, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::f, aji_client::forcessl, free, aji_client::jid, aji_client::keepalive, LOG_ERROR, malloc, aji_client::message_timeout, aji_client::mid, ast_variable::name, ast_variable::next, 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 ast_variable::value.

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

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

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

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

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

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, read]

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, read]

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(), 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 1117 of file res_jabber.c.

Referenced by aji_act_hook().

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

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

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

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

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

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

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

handles subscription requests.

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

Definition at line 1383 of file res_jabber.c.

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

Referenced by aji_act_hook().

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

static int aji_highest_bit ( int  number  )  [static]

Detects the highest bit in a number.

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

Definition at line 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, JABBER_CONFIG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_variable::value, 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.

Parameters:
aji_client struct, and xml packet.
Returns:
IKS_FILTER_EAT.
attempts to register to a transport step 2.
Parameters:
aji_client struct, and xml packet.
Returns:
IKS_FILTER_EAT.
goes through roster and prunes users not needed in list, or adds them accordingly.
Parameters:
aji_client struct.
Returns:
void.

Definition at line 1692 of file res_jabber.c.

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

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

static int aji_reconnect ( struct aji_client client  )  [static]

Definition at line 1817 of file res_jabber.c.

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

Referenced by aji_recv_loop().

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

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

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1541 of file res_jabber.c.

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

Referenced by aji_reload().

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

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

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

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

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

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

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

static int aji_reload ( void   )  [static]

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

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

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, clients, and RESULT_SUCCESS.

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

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

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

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1925 of file res_jabber.c.

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

Referenced by unload_module().

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

struct aji_client* ast_aji_get_client ( const char *  name  )  [read]

grab a aji_client structure by label name.

Parameters:
void. 
Returns:
1.

Definition at line 2366 of file res_jabber.c.

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

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

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

struct aji_client_container* ast_aji_get_clients ( void   )  [read]

Definition at line 2376 of file res_jabber.c.

References clients.

Referenced by gtalk_load_config().

02377 {
02378    return &clients;
02379 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

Definition at line 1585 of file res_jabber.c.

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

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

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

invite to a chatroom.

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

Definition at line 1506 of file res_jabber.c.

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

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

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1478 of file res_jabber.c.

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

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

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

sends messages.

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

Definition at line 1433 of file res_jabber.c.

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

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

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

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

static int gtalk_yuck ( iks *  node  )  [static]

Definition at line 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]

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

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

Referenced by load_module().

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

static int reload ( void   )  [static]

Definition at line 2498 of file res_jabber.c.

References aji_reload().

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

static int unload_module ( void   )  [static]

Definition at line 2451 of file res_jabber.c.

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

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


Variable Documentation

struct ast_cli_entry aji_cli[] [static]

Definition at line 131 of file res_jabber.c.

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.

Definition at line 176 of file res_jabber.c.

Referenced by ast_request_with_uniqueid().

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

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 Sat Apr 12 07:12:54 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5