Sat Aug 6 00:40:03 2011

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"

Go to the source code of this file.

Defines

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int aji_act_hook (void *data, int type, iks *node)
 The action hook parses the inbound packets, constantly running.
static void aji_buddy_destroy (struct aji_buddy *obj)
 Deletes the aji_buddy data structure.
static int aji_client_connect (void *data, ikspak *pak)
 connects as a client to jabber server.
static void aji_client_destroy (struct aji_client *obj)
 Deletes the aji_client data structure.
static int aji_client_info_handler (void *data, ikspak *pak)
static int aji_client_initialize (struct aji_client *client)
 prepares client for connect.
static int aji_component_initialize (struct aji_client *client)
 prepares component for connect.
static int aji_create_buddy (char *label, struct aji_client *client)
 creates transport. creates buddy.
static int aji_create_client (char *label, struct ast_variable *var, int debug)
 creates aji_client structure.
static int aji_dinfo_handler (void *data, ikspak *pak)
static int aji_ditems_handler (void *data, ikspak *pak)
static int aji_do_debug (int fd, int argc, char *argv[])
 turnon console debugging.
static int aji_do_reload (int fd, int argc, char *argv[])
 reload jabber module.
static int aji_filter_roster (void *data, ikspak *pak)
 filters the roster packet we get back from server.
static struct aji_resourceaji_find_resource (struct aji_buddy *buddy, char *name)
static struct aji_versionaji_find_version (char *node, char *version, ikspak *pak)
 Find version in XML stream and populate our capabilities list.
static int aji_get_roster (struct aji_client *client)
static void aji_handle_iq (struct aji_client *client, iks *node)
 Handles <iq> tags.
static void aji_handle_message (struct aji_client *client, ikspak *pak)
 Handles presence packets.
static void aji_handle_presence (struct aji_client *client, ikspak *pak)
static void aji_handle_subscribe (struct aji_client *client, ikspak *pak)
 handles subscription requests.
static int aji_highest_bit (int number)
 Detects the highest bit in a number.
static int aji_load_config (void)
 load config file.
static void aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming)
 the debug loop.
static int aji_no_debug (int fd, int argc, char *argv[])
 turnoff console debugging.
static void aji_pruneregister (struct aji_client *client)
 attempts to register to a transport. attempts to register to a transport step 2. goes through roster and prunes users not needed in list, or adds them accordingly.
static int aji_reconnect (struct aji_client *client)
static void * aji_recv_loop (void *data)
 receive message loop.
static int aji_register_approve_handler (void *data, ikspak *pak)
static int aji_register_query_handler (void *data, ikspak *pak)
static int aji_reload (void)
static int aji_send_exec (struct ast_channel *chan, void *data)
 Dial plan function to send a message.
static void aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc)
 set presence of client.
static int aji_show_clients (int fd, int argc, char *argv[])
 show client status.
static int aji_status_exec (struct ast_channel *chan, void *data)
 Dial plan function status(). puts the status of watched user into a channel variable.
static int aji_test (int fd, int argc, char *argv[])
 send test message for debugging.
int ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic)
 create a chatroom.
int ast_aji_disconnect (struct aji_client *client)
 disconnect from jabber server.
aji_clientast_aji_get_client (const char *name)
 grab a aji_client structure by label name or JID (without the resource string)
aji_client_containerast_aji_get_clients (void)
void ast_aji_increment_mid (char *mid)
 increments the mid field for messages and other events.
int ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message)
 invite to a chatroom.
int ast_aji_join_chat (struct aji_client *client, char *room)
 join a chatroom.
int ast_aji_send (struct aji_client *client, const char *address, const char *message)
 sends messages.
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_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, }
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"
static const struct ast_module_infoast_module_info = &__mod_info
aji_capabilitiescapabilities = NULL
aji_client_container clients
static char debug_usage []
static struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER }
 Global flags, initialized to default values.
static char mandescr_jabber_send []
static char no_debug_usage []
static char reload_usage []
static char test_usage []
static int tls_initialized = FALSE


Detailed Description

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

Todo:
If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?

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 void __reg_module ( void   )  [static]

Definition at line 2521 of file res_jabber.c.

static void __unreg_module ( void   )  [static]

Definition at line 2521 of file res_jabber.c.

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

The action hook parses the inbound packets, constantly running.

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

Definition at line 488 of file res_jabber.c.

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

Referenced by aji_create_client().

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

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

01856 {
01857    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01858    int res = IKS_FILTER_PASS;
01859 
01860    if (client) {
01861       if (client->state == AJI_DISCONNECTED) {
01862          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);
01863          client->state = AJI_CONNECTING;
01864          client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
01865          if (!client->component) { /*client*/
01866             aji_get_roster(client);
01867          }
01868          iks_filter_remove_hook(client->f, aji_client_connect);
01869          /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */
01870          res = IKS_FILTER_EAT;
01871       }
01872    } else
01873       ast_log(LOG_ERROR, "Out of memory.\n");
01874 
01875    ASTOBJ_UNREF(client, aji_client_destroy);
01876    return res;
01877 }

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::list, aji_message::message, aji_client::messages, 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 906 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().

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

static int aji_client_initialize ( struct aji_client client  )  [static]

prepares client for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1884 of file res_jabber.c.

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

Referenced by aji_reconnect().

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

static int aji_component_initialize ( struct aji_client client  )  [static]

prepares component for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1906 of file res_jabber.c.

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

Referenced by aji_reconnect().

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

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

creates transport. creates buddy.

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

Definition at line 2295 of file res_jabber.c.

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

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

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

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

creates aji_client structure.

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

Definition at line 2106 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_copy_string(), ast_false(), AST_FLAGS_ALL, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::f, aji_client::forcessl, free, globalflags, aji_client::jid, aji_client::keepalive, LOG_ERROR, malloc, aji_client::message_timeout, aji_client::messages, aji_client::mid, aji_client::name, aji_client::p, aji_client::password, aji_client::port, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and var.

Referenced by aji_load_config().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 295 of file res_jabber.c.

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

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

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

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

Find version in XML stream and populate our capabilities list.

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

Definition at line 233 of file res_jabber.c.

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

Referenced by aji_handle_presence().

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

static int aji_get_roster ( struct aji_client client  )  [static]

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

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

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

Referenced by aji_act_hook().

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

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

References aji_message::arrived, ast_calloc, ast_copy_string(), 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::list, aji_message::message, aji_client::message_timeout, and aji_client::messages.

Referenced by aji_act_hook().

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

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

Definition at line 1165 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_copy_string(), 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().

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

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

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

Referenced by aji_act_hook().

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

static int aji_highest_bit ( int  number  )  [static]

Detects the highest bit in a number.

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

Definition at line 322 of file res_jabber.c.

Referenced by aji_act_hook().

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

static int aji_load_config ( void   )  [static]

load config file.

Parameters:
void. 
Returns:
1.

Definition at line 2327 of file res_jabber.c.

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

Referenced by aji_reload().

02328 {
02329    char *cat = NULL;
02330    int debug = 0;
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(), aji_client::name, 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 2005 of file res_jabber.c.

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

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

static void aji_pruneregister ( struct aji_client client  )  [static]

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

Parameters:
aji_client struct.
Returns:
void.

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

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

static int aji_reconnect ( struct aji_client client  )  [static]

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

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

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

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1540 of file res_jabber.c.

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

Referenced by aji_reload().

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

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

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

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

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

Definition at line 740 of file res_jabber.c.

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

Referenced by aji_create_client().

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

static int aji_reload ( void   )  [static]

Definition at line 2443 of file res_jabber.c.

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

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

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

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

Dial plan function to send a message.

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

Definition at line 425 of file res_jabber.c.

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

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

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

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

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

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

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, and aji_resource::status.

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

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

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

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

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

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

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

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

struct aji_client* ast_aji_get_client ( const char *  name  ) 

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

Parameters:
name label or JID
Returns:
aji_client.

Definition at line 2367 of file res_jabber.c.

References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, and clients.

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

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

struct aji_client_container* ast_aji_get_clients ( void   ) 

Definition at line 2389 of file res_jabber.c.

References clients.

02390 {
02391    return &clients;
02392 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

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

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

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

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

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

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1477 of file res_jabber.c.

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

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

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

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

static int gtalk_yuck ( iks *  node  )  [static]

Definition at line 310 of file res_jabber.c.

Referenced by aji_handle_presence().

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

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

Definition at line 334 of file res_jabber.c.

References ast_sha1_hash().

Referenced by aji_act_hook().

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

static int load_module ( void   )  [static]

Definition at line 2497 of file res_jabber.c.

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

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

Send a Jabber Message via call from the Manager.

Definition at line 2402 of file res_jabber.c.

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

Referenced by load_module().

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

static int reload ( void   )  [static]

Definition at line 2511 of file res_jabber.c.

References aji_reload().

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

static int unload_module ( void   )  [static]

Definition at line 2464 of file res_jabber.c.

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

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 2521 of file res_jabber.c.

struct ast_cli_entry aji_cli[] [static]

Definition at line 131 of file res_jabber.c.

Referenced by load_module(), and unload_module().

char* ajisend_descrip [static]

Initial value:

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

Definition at line 157 of file res_jabber.c.

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

Definition at line 155 of file res_jabber.c.

char* ajistatus_descrip [static]

Definition at line 167 of file res_jabber.c.

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

Definition at line 165 of file res_jabber.c.

char* app_ajisend = "JabberSend" [static]

Definition at line 153 of file res_jabber.c.

char* app_ajistatus = "JabberStatus" [static]

Definition at line 163 of file res_jabber.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 2521 of file res_jabber.c.

struct aji_capabilities* capabilities = NULL

Definition at line 176 of file res_jabber.c.

Referenced by aji_find_version(), and ast_request().

struct aji_client_container clients

Definition at line 175 of file res_jabber.c.

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

char debug_usage[] [static]

Initial value:

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

Definition at line 114 of file res_jabber.c.

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

Global flags, initialized to default values.

Definition at line 179 of file res_jabber.c.

char mandescr_jabber_send[] [static]

Definition at line 2394 of file res_jabber.c.

Referenced by load_module().

char no_debug_usage[] [static]

Initial value:

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

Definition at line 118 of file res_jabber.c.

char reload_usage[] [static]

Initial value:

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

Definition at line 122 of file res_jabber.c.

char test_usage[] [static]

Initial value:

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

Definition at line 126 of file res_jabber.c.

int tls_initialized = FALSE [static]

Definition at line 180 of file res_jabber.c.


Generated on Sat Aug 6 00:40:03 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7