Wed Aug 15 01:25:29 2007

Asterisk developer's documentation


res_jabber.c File Reference

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

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

Include dependency graph for res_jabber.c:

Go to the source code of this file.

Defines

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

Functions

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

Variables

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


Detailed Description

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

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

Definition in file res_jabber.c.


Define Documentation

#define FALSE   0

Definition at line 64 of file res_jabber.c.

#define JABBER_CONFIG   "jabber.conf"

Definition at line 61 of file res_jabber.c.

Referenced by aji_load_config().

#define TRUE   1

Definition at line 68 of file res_jabber.c.


Function Documentation

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

The action hook parses the inbound packets, constantly running.

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

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

00488 {
00489    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
00490    ikspak *pak = NULL;
00491    iks *auth = NULL;
00492 
00493    if(!node) {
00494       ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */
00495       ASTOBJ_UNREF(client, aji_client_destroy);
00496       return IKS_HOOK;
00497    }
00498 
00499    if (client->state == AJI_DISCONNECTING) {
00500       ASTOBJ_UNREF(client, aji_client_destroy);
00501       return IKS_HOOK;
00502    }
00503 
00504    pak = iks_packet(node);
00505 
00506    if (!client->component) { /*client */
00507       switch (type) {
00508       case IKS_NODE_START:
00509          if (client->usetls && !iks_is_secure(client->p)) {
00510             if (iks_has_tls()) {
00511                iks_start_tls(client->p);
00512                tls_initialized = TRUE;
00513             } else
00514                ast_log(LOG_ERROR, "gnuTLS not installed. You need to recompile the Iksemel library with gnuTLS support\n");
00515             break;
00516          }
00517          if (!client->usesasl) {
00518             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);
00519             auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id"));
00520             if (auth) {
00521                iks_insert_attrib(auth, "id", client->mid);
00522                iks_insert_attrib(auth, "to", client->jid->server);
00523                ast_aji_increment_mid(client->mid);
00524                iks_send(client->p, auth);
00525                iks_delete(auth);
00526             } else
00527                ast_log(LOG_ERROR, "Out of memory.\n");
00528          }
00529          break;
00530 
00531       case IKS_NODE_NORMAL:
00532          {
00533             int features = 0;
00534             if (!strcmp("stream:features", iks_name(node))) {
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                               ast_base64encode(base64, (const unsigned char *) s, len, len * 2);
00586                               iks_insert_cdata(x, base64, 0);
00587                               iks_send(client->p, x);
00588                               iks_delete(x);
00589                               if (base64)
00590                                  free(base64);
00591                               if (s)
00592                                  free(s);
00593                            } else {
00594                               ast_log(LOG_ERROR, "Out of memory.\n");
00595                            }
00596                         }
00597                      }
00598                   }
00599                }
00600             } else if (!strcmp("failure", iks_name(node))) {
00601                ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n");
00602             } else if (!strcmp("success", iks_name(node))) {
00603                client->authorized = 1;
00604                iks_send_header(client->p, client->jid->server);
00605             }
00606             break;
00607          }
00608       case IKS_NODE_ERROR: 
00609             ast_log(LOG_ERROR, "JABBER: Node Error\n");
00610             ASTOBJ_UNREF(client, aji_client_destroy);
00611             return IKS_HOOK;
00612             break;
00613       case IKS_NODE_STOP: 
00614             ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00615             ASTOBJ_UNREF(client, aji_client_destroy);
00616             return IKS_HOOK;
00617             break;
00618       }
00619    } else if (client->state != AJI_CONNECTED && client->component) {
00620       switch (type) {
00621       case IKS_NODE_START:
00622          if (client->state == AJI_DISCONNECTED) {
00623             char secret[160], shasum[320], *handshake;
00624 
00625             sprintf(secret, "%s%s", pak->id, client->password);
00626             ast_sha1_hash(shasum, secret);
00627             handshake = NULL;
00628             asprintf(&handshake, "<handshake>%s</handshake>", shasum);
00629             if (handshake) {
00630                iks_send_raw(client->p, handshake);
00631                free(handshake);
00632                handshake = NULL;
00633             }
00634             client->state = AJI_CONNECTING;
00635             if(iks_recv(client->p,1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/
00636                client->state = AJI_CONNECTED;
00637             else
00638                ast_log(LOG_WARNING,"Jabber didn't seem to handshake, failed to authenicate.\n");
00639             break;
00640          }
00641          break;
00642 
00643       case IKS_NODE_NORMAL:
00644          break;
00645 
00646       case IKS_NODE_ERROR:
00647          ast_log(LOG_ERROR, "JABBER: Node Error\n");
00648          ASTOBJ_UNREF(client, aji_client_destroy);
00649          return IKS_HOOK;
00650 
00651       case IKS_NODE_STOP:
00652          ast_log(LOG_WARNING, "JABBER: Disconnected\n");
00653          ASTOBJ_UNREF(client, aji_client_destroy);
00654          return IKS_HOOK;
00655       }
00656    }
00657 
00658    switch (pak->type) {
00659    case IKS_PAK_NONE:
00660       if (option_debug)
00661          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you NONE\n");
00662       break;
00663    case IKS_PAK_MESSAGE:
00664       aji_handle_message(client, pak);
00665       if (option_debug)
00666          ast_log(LOG_DEBUG, "JABBER: I Don't know what to do with you MESSAGE\n");
00667       break;
00668    case IKS_PAK_PRESENCE:
00669       aji_handle_presence(client, pak);
00670       if (option_debug)
00671          ast_log(LOG_DEBUG, "JABBER: I Do know how to handle presence!!\n");
00672       break;
00673    case IKS_PAK_S10N:
00674       aji_handle_subscribe(client, pak);
00675       if (option_debug)
00676          ast_log(LOG_DEBUG, "JABBER: I Dont know S10N subscribe!!\n");
00677       break;
00678    case IKS_PAK_IQ:
00679       if (option_debug)
00680          ast_log(LOG_DEBUG, "JABBER: I Dont have an IQ!!!\n");
00681       aji_handle_iq(client, node);
00682       break;
00683    default:
00684       if (option_debug)
00685          ast_log(LOG_DEBUG, "JABBER: I Dont know %i\n", pak->type);
00686       break;
00687    }
00688    
00689    iks_filter_packet(client->f, pak);
00690 
00691    if (node)
00692       iks_delete(node);
00693 
00694    ASTOBJ_UNREF(client, aji_client_destroy);
00695    return IKS_OK;
00696 }

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

01830 {
01831    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01832    int res = 0;
01833 
01834    if (client) {
01835       if (client->state == AJI_DISCONNECTED) {
01836          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);
01837          client->state = AJI_CONNECTING;
01838          client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
01839          iks_filter_remove_hook(client->f, aji_client_connect);
01840          if(!client->component) /*client*/
01841             aji_get_roster(client);
01842       }
01843    } else
01844       ast_log(LOG_ERROR, "Out of memory.\n");
01845 
01846    ASTOBJ_UNREF(client, aji_client_destroy);
01847    return res;
01848 }

static void aji_client_destroy ( struct aji_client obj  )  [static]

Deletes the aji_client data structure.

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

Definition at line 187 of file res_jabber.c.

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

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

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

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

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

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

static int aji_client_initialize ( struct aji_client client  )  [static]

prepares client for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1855 of file res_jabber.c.

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

Referenced by aji_reconnect().

01856 {
01857    int connected = 0;
01858 
01859    connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->jid->server);
01860 
01861    if (connected == IKS_NET_NOCONN) {
01862       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01863       return IKS_HOOK;
01864    } else   if (connected == IKS_NET_NODNS) {
01865       ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01866       return IKS_HOOK;
01867    } else
01868       iks_recv(client->p, 30);
01869    return IKS_OK;
01870 }

static int aji_component_initialize ( struct aji_client client  )  [static]

prepares component for connect.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1877 of file res_jabber.c.

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

Referenced by aji_reconnect().

01878 {
01879    int connected = 1;
01880 
01881    connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->user);
01882    if (connected == IKS_NET_NOCONN) {
01883       ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n");
01884       return IKS_HOOK;
01885    } else if (connected == IKS_NET_NODNS) {
01886       ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to  %s\n", client->name, S_OR(client->serverhost, client->jid->server));
01887       return IKS_HOOK;
01888    } else if (!connected) 
01889       iks_recv(client->p, 30);
01890    return IKS_OK;
01891 }

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

creates transport.

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

Definition at line 2268 of file res_jabber.c.

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

Referenced by aji_create_client(), and aji_handle_presence().

02269 {
02270    struct aji_buddy *buddy = NULL;
02271    int flag = 0;
02272    buddy = ASTOBJ_CONTAINER_FIND(&client->buddies,label);
02273    if (!buddy) {
02274       flag = 1;
02275       buddy = malloc(sizeof(struct aji_buddy));
02276       if(!buddy) {
02277          ast_log(LOG_WARNING, "Out of memory\n");
02278          return 0;
02279       }
02280       memset(buddy, 0, sizeof(struct aji_buddy));
02281       ASTOBJ_INIT(buddy);
02282    }
02283    ASTOBJ_WRLOCK(buddy);
02284    ast_copy_string(buddy->name, label, sizeof(buddy->name));
02285    ASTOBJ_UNLOCK(buddy);
02286    if(flag)
02287       ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
02288    else {
02289       ASTOBJ_UNMARK(buddy);
02290       ASTOBJ_UNREF(buddy, aji_buddy_destroy);
02291    }
02292    return 1;
02293 }

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

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

Referenced by aji_load_config().

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

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

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

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

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

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

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

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

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

01949 {
01950    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01951       ASTOBJ_RDLOCK(iterator); 
01952       iterator->debug = 1;
01953       ASTOBJ_UNLOCK(iterator);
01954    });
01955    ast_cli(fd, "Jabber Debugging Enabled.\n");
01956    return RESULT_SUCCESS;
01957 }

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

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

01965 {
01966    aji_reload();
01967    ast_cli(fd, "Jabber Reloaded.\n");
01968    return RESULT_SUCCESS;
01969 }

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

01719 {
01720    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01721    int flag = 0;
01722    iks *x = NULL;
01723    struct aji_buddy *buddy;
01724    
01725    client->state = AJI_CONNECTED;
01726    ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01727       ASTOBJ_RDLOCK(iterator);
01728       x = iks_child(pak->query);
01729       flag = 0;
01730       while (x) {
01731          if (!iks_strcmp(iks_name(x), "item")) {
01732             if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) {
01733                flag = 1;
01734                ast_clear_flag(iterator, AJI_AUTOPRUNE | AJI_AUTOREGISTER);
01735             }
01736          }
01737          x = iks_next(x);
01738       }
01739       if (!flag)
01740          ast_copy_flags(iterator, client, AJI_AUTOREGISTER);
01741       if (x)
01742          iks_delete(x);
01743       ASTOBJ_UNLOCK(iterator);
01744    });
01745 
01746    x = iks_child(pak->query);
01747    while (x) {
01748       flag = 0;
01749       if (iks_strcmp(iks_name(x), "item") == 0) {
01750          ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01751             ASTOBJ_RDLOCK(iterator);
01752             if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid")))
01753                flag = 1;
01754             ASTOBJ_UNLOCK(iterator);
01755          });
01756 
01757          if (!flag) {
01758             buddy = (struct aji_buddy *) malloc(sizeof(struct aji_buddy));
01759             if (!buddy) {
01760                ast_log(LOG_WARNING, "Out of memory\n");
01761                return 0;
01762             }
01763             memset(buddy, 0, sizeof(struct aji_buddy));
01764             ASTOBJ_INIT(buddy);
01765             ASTOBJ_WRLOCK(buddy);
01766             ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name));
01767             ast_clear_flag(buddy, AST_FLAGS_ALL);
01768             if(ast_test_flag(client, AJI_AUTOPRUNE)) {
01769                ast_set_flag(buddy, AJI_AUTOPRUNE);
01770                buddy->objflags |= ASTOBJ_FLAG_MARKED;
01771             } else
01772                ast_set_flag(buddy, AJI_AUTOREGISTER);
01773             ASTOBJ_UNLOCK(buddy);
01774             if (buddy) {
01775                ASTOBJ_CONTAINER_LINK(&client->buddies, buddy);
01776                ASTOBJ_UNREF(buddy, aji_buddy_destroy);
01777             }
01778          }
01779       }
01780       x = iks_next(x);
01781    }
01782    if (x)
01783       iks_delete(x);
01784    aji_pruneregister(client);
01785 
01786    ASTOBJ_UNREF(client, aji_client_destroy);
01787    return IKS_FILTER_EAT;
01788 }

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

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

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

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

Find version in XML stream and populate our capabilities list.

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

Definition at line 233 of file res_jabber.c.

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

Referenced by aji_handle_presence().

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

static int aji_get_roster ( struct aji_client client  )  [static]

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

01811 {
01812    iks *roster = NULL;
01813    roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
01814    if(roster) {
01815       iks_insert_attrib(roster, "id", "roster");
01816       aji_set_presence(client, NULL, client->jid->full, 1, client->statusmessage);
01817       iks_send(client->p, roster);
01818    }
01819    if (roster)
01820       iks_delete(roster);
01821    return 1;
01822 }

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

Referenced by aji_act_hook().

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

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

References aji_message::arrived, ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_strdup, free, aji_message::from, aji_message::id, aji_message::message, and aji_client::message_timeout.

Referenced by aji_act_hook().

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

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

Definition at line 1162 of file res_jabber.c.

References aji_buddy_destroy(), AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_increment_mid(), ast_log(), ast_strdup, ast_verbose(), ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, descrip, aji_resource::description, free, gtalk_yuck(), last, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, malloc, aji_client::mid, aji_resource::next, option_debug, option_verbose, aji_client::p, aji_resource::priority, aji_resource::resource, aji_buddy::resources, aji_client::state, aji_resource::status, aji_client::statusmessage, type, and VERBOSE_PREFIX_3.

Referenced by aji_act_hook().

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

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

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

Referenced by aji_act_hook().

01357 {
01358    if(pak->subtype == IKS_TYPE_SUBSCRIBE) { 
01359       iks *presence = NULL, *status = NULL;
01360       presence = iks_new("presence");
01361       status = iks_new("status");
01362       if(presence && status) {
01363          iks_insert_attrib(presence, "type", "subscribed");
01364          iks_insert_attrib(presence, "to", pak->from->full);
01365          iks_insert_attrib(presence, "from", client->jid->full);
01366          if(pak->id)
01367             iks_insert_attrib(presence, "id", pak->id);
01368          iks_insert_cdata(status, "Asterisk has approved subscription", 0);
01369          iks_insert_node(presence, status);
01370          iks_send(client->p, presence);
01371       } else
01372          ast_log(LOG_ERROR, "Unable to allocate nodes\n");
01373       if(presence)
01374          iks_delete(presence);
01375       if(status)
01376          iks_delete(status);
01377       if(client->component)
01378          aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), 1, client->statusmessage);
01379    }
01380    if (option_verbose > 4) {
01381       switch (pak->subtype) {
01382       case IKS_TYPE_SUBSCRIBE:
01383          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01384          break;
01385       case IKS_TYPE_SUBSCRIBED:
01386          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01387          break;
01388       case IKS_TYPE_UNSUBSCRIBE:
01389          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01390          break;
01391       case IKS_TYPE_UNSUBSCRIBED:
01392          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01393          break;
01394       default:          /*IKS_TYPE_ERROR: */
01395          ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype);
01396          break;
01397       }
01398    }
01399 }

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

Referenced by aji_act_hook().

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

static int aji_load_config ( void   )  [static]

load config file.

Parameters:
void. 
Returns:
1.

Definition at line 2300 of file res_jabber.c.

References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), ast_category_browse(), ast_config_load(), ast_false(), ast_log(), ast_set2_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), debug, JABBER_CONFIG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by aji_reload().

02301 {
02302    char *cat = NULL;
02303    int debug = 1;
02304    struct ast_config *cfg = NULL;
02305    struct ast_variable *var = NULL;
02306 
02307    cfg = ast_config_load(JABBER_CONFIG);
02308    if (!cfg) {
02309       ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG);
02310       return 0;
02311    }
02312 
02313    cat = ast_category_browse(cfg, NULL);
02314    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
02315       if (!strcasecmp(var->name, "debug"))
02316          debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1;
02317       else if (!strcasecmp(var->name, "autoprune"))
02318          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE);
02319       else if (!strcasecmp(var->name, "autoregister"))
02320          ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER);
02321    }
02322 
02323    while (cat) {
02324       if (strcasecmp(cat, "general")) {
02325             var = ast_variable_browse(cfg, cat);
02326             aji_create_client(cat, var, debug);
02327       }
02328       cat = ast_category_browse(cfg, cat);
02329    }
02330    return 1;
02331 }

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

References aji_client_destroy(), ast_verbose(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::debug, EVENT_FLAG_USER, manager_event(), and option_debug.

Referenced by aji_create_client().

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

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

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

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

static void aji_pruneregister ( struct aji_client client  )  [static]

attempts to register to a transport.

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

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

01666 {
01667    int res = 0;
01668    iks *removeiq = iks_new("iq");
01669    iks *removequery = iks_new("query");
01670    iks *removeitem = iks_new("item");
01671    iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items");
01672 
01673    if (client && removeiq && removequery && removeitem && send) {
01674       iks_insert_node(removeiq, removequery);
01675       iks_insert_node(removequery, removeitem);
01676       ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
01677          ASTOBJ_RDLOCK(iterator);
01678          /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never
01679           * be called at the same time */
01680          if (ast_test_flag(iterator, AJI_AUTOPRUNE)) {
01681             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
01682                   "GoodBye your status is no longer needed by Asterisk the Open Source PBX"
01683                   " so I am no longer subscribing to your presence.\n"));
01684             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
01685                   "GoodBye you are no longer in the asterisk config file so I am removing"
01686                   " your access to my presence.\n"));
01687             iks_insert_attrib(removeiq, "from", client->jid->full); 
01688             iks_insert_attrib(removeiq, "type", "set"); 
01689             iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster");
01690             iks_insert_attrib(removeitem, "jid", iterator->name);
01691             iks_insert_attrib(removeitem, "subscription", "remove");
01692             res = iks_send(client->p, removeiq);
01693          } else if (ast_test_flag(iterator, AJI_AUTOREGISTER)) {
01694             res = iks_send(client->p, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 
01695                   "Greetings I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
01696             ast_clear_flag(iterator, AJI_AUTOREGISTER);
01697          }
01698          ASTOBJ_UNLOCK(iterator);
01699       });
01700    } else
01701       ast_log(LOG_ERROR, "Out of memory.\n");
01702    if (removeiq)
01703       iks_delete(removeiq);
01704    if (removequery)
01705       iks_delete(removequery);
01706    if (removeitem)
01707       iks_delete(removeitem);
01708    if (send)
01709       iks_delete(send);
01710    ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy);
01711 }

static int aji_reconnect ( struct aji_client client  )  [static]

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

01791 {
01792    int res = 0;
01793 
01794    if (client->state)
01795       client->state = AJI_DISCONNECTED;
01796    client->timeout=50;
01797    if (client->p)
01798       iks_parser_reset(client->p);
01799    if (client->authorized)
01800       client->authorized = 0;
01801 
01802    if(client->component)
01803       res = aji_component_initialize(client);
01804    else
01805       res = aji_client_initialize(client);
01806 
01807    return res;
01808 }

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

receive message loop.

Parameters:
aji_client struct.
Returns:
void.

Definition at line 1514 of file res_jabber.c.

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

Referenced by aji_reload().

01515 {
01516    struct aji_client *client = ASTOBJ_REF((struct aji_client *) data);
01517    int res = IKS_HOOK;
01518    do {
01519       if (res != IKS_OK) {
01520          while(res != IKS_OK) {
01521             if(option_verbose > 3)
01522                ast_verbose("JABBER: reconnecting.\n");
01523             res = aji_reconnect(client);
01524             sleep(4);
01525          }
01526       }
01527 
01528       res = iks_recv(client->p, 1);
01529 
01530       if (client->state == AJI_DISCONNECTING) {
01531          if (option_debug > 1)
01532             ast_log(LOG_DEBUG, "Ending our Jabber client's thread due to a disconnect\n");
01533          pthread_exit(NULL);
01534       }
01535       client->timeout--;
01536       if (res == IKS_HOOK) 
01537          ast_log(LOG_WARNING, "JABBER: Got hook event.\n");
01538       else if (res == IKS_NET_TLSFAIL)
01539          ast_log(LOG_WARNING, "JABBER:  Failure in TLS.\n");
01540       else if (client->timeout == 0 && client->state == AJI_CONNECTED) {
01541          res = iks_send_raw(client->p, " ");
01542          if(res == IKS_OK)
01543             client->timeout = 50;
01544          else
01545             ast_log(LOG_WARNING, "JABBER:  Network Timeout\n");
01546       } else if (res == IKS_NET_RWERR)
01547          ast_log(LOG_WARNING, "JABBER: socket read error\n");
01548    } while (client);
01549    ASTOBJ_UNREF(client, aji_client_destroy);
01550    return 0;
01551 }

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

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

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

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

Definition at line 737 of file res_jabber.c.

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

Referenced by aji_create_client().

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

static int aji_reload ( void   )  [static]

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

02403 {
02404    ASTOBJ_CONTAINER_MARKALL(&clients);
02405    if (!aji_load_config()) {
02406       ast_log(LOG_ERROR, "JABBER: Failed to load config.\n");
02407       return 0;
02408    }
02409    ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy);
02410    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02411       ASTOBJ_RDLOCK(iterator);
02412       if(iterator->state == AJI_DISCONNECTED) {
02413          if (!iterator->thread)
02414             ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator);
02415       } else if (iterator->state == AJI_CONNECTING)
02416          aji_get_roster(iterator);
02417       ASTOBJ_UNLOCK(iterator);
02418    });
02419    
02420    return 1;
02421 }

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

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

Referenced by load_module().

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

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

01917 {
01918    int res = 0;
01919    iks *presence = iks_make_pres(level, desc);
01920    iks *cnode = iks_new("c");
01921    iks *priority = iks_new("priority");
01922 
01923    iks_insert_cdata(priority, "0", 1);
01924    if (presence && cnode && client) {
01925       if(to)
01926          iks_insert_attrib(presence, "to", to);
01927       if(from)
01928          iks_insert_attrib(presence, "from", from);
01929       iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
01930       iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
01931       iks_insert_attrib(cnode, "ext", "voice-v1");
01932       iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
01933       iks_insert_node(presence, cnode);
01934       res = iks_send(client->p, presence);
01935    } else
01936       ast_log(LOG_ERROR, "Out of memory.\n");
01937    if (cnode)
01938       iks_delete(cnode);
01939    if (presence)
01940       iks_delete(presence);
01941 }

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

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

01993 {
01994    char *status;
01995    int count = 0;
01996    ast_cli(fd, "Jabber Users and their status:\n");
01997    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
01998       ASTOBJ_RDLOCK(iterator);
01999       count++;
02000       switch (iterator->state) {
02001       case AJI_DISCONNECTED:
02002          status = "Disconnected";
02003          break;
02004       case AJI_CONNECTING:
02005          status = "Connecting";
02006          break;
02007       case AJI_CONNECTED:
02008          status = "Connected";
02009          break;
02010       default:
02011          status = "Unknown";
02012       }
02013       ast_cli(fd, "       User: %s     - %s\n", iterator->user, status);
02014       ASTOBJ_UNLOCK(iterator);
02015    });
02016    ast_cli(fd, "----\n");
02017    ast_cli(fd, "   Number of users: %d\n", count);
02018    return RESULT_SUCCESS;
02019 }

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

References aji_find_resource(), ast_aji_get_client(), ast_log(), ast_strdupa, ASTOBJ_CONTAINER_FIND, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), aji_resource::resource, aji_buddy::resources, s, aji_resource::status, and strsep().

Referenced by load_module().

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

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

02027 {
02028    struct aji_client *client;
02029    struct aji_resource *resource;
02030    const char *name = "asterisk";
02031    struct aji_message *tmp;
02032 
02033    if (argc > 3)
02034       return RESULT_SHOWUSAGE;
02035    else if (argc == 3)
02036       name = argv[2];
02037 
02038    if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) {
02039       ast_cli(fd, "Unable to find client '%s'!\n", name);
02040       return RESULT_FAILURE;
02041    }
02042 
02043    /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */
02044    ast_aji_send(client, "mogorman@astjab.org", "blahblah");
02045    ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, {
02046       ASTOBJ_RDLOCK(iterator);
02047       ast_verbose("User: %s\n", iterator->name);
02048       for (resource = iterator->resources; resource; resource = resource->next) {
02049          ast_verbose("Resource: %s\n", resource->resource);
02050          if(resource->cap) {
02051             ast_verbose("   client: %s\n", resource->cap->parent->node);
02052             ast_verbose("   version: %s\n", resource->cap->version);
02053             ast_verbose("   Jingle Capable: %d\n", resource->cap->jingle);
02054          }
02055          ast_verbose("  Priority: %d\n", resource->priority);
02056          ast_verbose("  Status: %d\n", resource->status); 
02057          ast_verbose("  Message: %s\n", S_OR(resource->description,"")); 
02058       }
02059       ASTOBJ_UNLOCK(iterator);
02060    });
02061    ast_verbose("\nOooh a working message stack!\n");
02062    AST_LIST_LOCK(&client->messages);
02063    AST_LIST_TRAVERSE(&client->messages, tmp, list) {
02064       ast_verbose("  Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, ""));
02065    }
02066    AST_LIST_UNLOCK(&client->messages);
02067    ASTOBJ_UNREF(client, aji_client_destroy);
02068 
02069    return RESULT_SUCCESS;
02070 }

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

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

01431 {
01432    int res = 0;
01433    iks *iq = NULL;
01434    iq = iks_new("iq");
01435    if (iq && client) {
01436       iks_insert_attrib(iq, "type", "get");
01437       iks_insert_attrib(iq, "to", server);
01438       iks_insert_attrib(iq, "id", client->mid);
01439       ast_aji_increment_mid(client->mid);
01440       iks_send(client->p, iq);
01441    } else 
01442       ast_log(LOG_ERROR, "Out of memory.\n");
01443    return res;
01444 }

int ast_aji_disconnect ( struct aji_client client  ) 

disconnect from jabber server.

Parameters:
aji_client struct.
Returns:
1.

Definition at line 1898 of file res_jabber.c.

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

01899 {
01900    if (client) {
01901       if (option_verbose > 3)
01902          ast_verbose(VERBOSE_PREFIX_3 "JABBER: Disconnecting\n");
01903       iks_disconnect(client->p);
01904       iks_parser_delete(client->p);
01905       ASTOBJ_UNREF(client, aji_client_destroy);
01906    }
01907 
01908    return 1;
01909 }

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

grab a aji_client structure by label name.

Parameters:
void. 
Returns:
1.

Definition at line 2338 of file res_jabber.c.

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

02339 {
02340    struct aji_client *client = NULL;
02341 
02342    client = ASTOBJ_CONTAINER_FIND(&clients, name);
02343    if (!client && !strchr(name, '@'))
02344       client = ASTOBJ_CONTAINER_FIND_FULL(&clients, name, user,,, strcasecmp);
02345    return client;
02346 }

struct aji_client_container* ast_aji_get_clients ( void   )  [read]

Definition at line 2348 of file res_jabber.c.

References clients.

02349 {
02350    return &clients;
02351 }

void ast_aji_increment_mid ( char *  mid  ) 

increments the mid field for messages and other events.

Parameters:
message id.
Returns:
void.

Definition at line 1558 of file res_jabber.c.

01559 {
01560    int i = 0;
01561 
01562    for (i = strlen(mid) - 1; i >= 0; i--) {
01563       if (mid[i] != 'z') {
01564          mid[i] = mid[i] + 1;
01565          i = 0;
01566       } else
01567          mid[i] = 'a';
01568    }
01569 }

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

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

01480 {
01481    int res = 0;
01482    iks *invite, *body, *namespace;
01483 
01484    invite = iks_new("message");
01485    body = iks_new("body");
01486    namespace = iks_new("x");
01487    if (client && invite && body && namespace) {
01488       iks_insert_attrib(invite, "to", user);
01489       iks_insert_attrib(invite, "id", client->mid);
01490       ast_aji_increment_mid(client->mid);
01491       iks_insert_cdata(body, message, 0);
01492       iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
01493       iks_insert_attrib(namespace, "jid", room);
01494       iks_insert_node(invite, body);
01495       iks_insert_node(invite, namespace);
01496       res = iks_send(client->p, invite);
01497    } else 
01498       ast_log(LOG_ERROR, "Out of memory.\n");
01499    if (body)
01500       iks_delete(body);
01501    if (namespace)
01502       iks_delete(namespace);
01503    if (invite)
01504       iks_delete(invite);
01505    return res;
01506 }

int ast_aji_join_chat ( struct aji_client client,
char *  room 
)

join a chatroom.

Parameters:
aji_client struct , room.
Returns:
res.

Definition at line 1451 of file res_jabber.c.

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

01452 {
01453    int res = 0;
01454    iks *presence = NULL, *priority = NULL;
01455    presence = iks_new("presence");
01456    priority = iks_new("priority");
01457    if (presence && priority && client) {
01458       iks_insert_cdata(priority, "0", 1);
01459       iks_insert_attrib(presence, "to", room);
01460       iks_insert_node(presence, priority);
01461       res = iks_send(client->p, presence);
01462       iks_insert_cdata(priority, "5", 1);
01463       iks_insert_attrib(presence, "to", room);
01464       res = iks_send(client->p, presence);
01465    } else 
01466       ast_log(LOG_ERROR, "Out of memory.\n");
01467    if (presence)
01468       iks_delete(presence);
01469    if (priority)
01470       iks_delete(priority);
01471    return res;
01472 }

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

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

01407 {
01408    int res = 0;
01409    iks *message_packet = NULL;
01410    if (client->state == AJI_CONNECTED) {
01411       message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message);
01412       if (message_packet) {
01413          iks_insert_attrib(message_packet, "from", client->jid->full);
01414          res = iks_send(client->p, message_packet);
01415       } else {
01416          ast_log(LOG_ERROR, "Out of memory.\n");
01417       }
01418       if (message_packet)
01419          iks_delete(message_packet);
01420    } else
01421       ast_log(LOG_WARNING, "JABBER: Not connected can't send\n");
01422    return 1;
01423 }

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

static int gtalk_yuck ( iks *  node  )  [static]

Definition at line 309 of file res_jabber.c.

Referenced by aji_handle_presence().

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

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

Definition at line 333 of file res_jabber.c.

References ast_sha1_hash().

Referenced by aji_act_hook().

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

static int load_module ( void   )  [static]

Definition at line 2456 of file res_jabber.c.

References 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, and manager_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 2361 of file res_jabber.c.

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

Referenced by load_module().

02362 {
02363    struct aji_client *client = NULL;
02364    const char *id = astman_get_header(m,"ActionID");
02365    const char *jabber = astman_get_header(m,"Jabber");
02366    const char *screenname = astman_get_header(m,"ScreenName");
02367    const char *message = astman_get_header(m,"Message");
02368 
02369    if (ast_strlen_zero(jabber)) {
02370       astman_send_error(s, m, "No transport specified");
02371       return 0;
02372    }
02373    if (ast_strlen_zero(screenname)) {
02374       astman_send_error(s, m, "No ScreenName specified");
02375       return 0;
02376    }
02377    if (ast_strlen_zero(message)) {
02378       astman_send_error(s, m, "No Message specified");
02379       return 0;
02380    }
02381 
02382    astman_send_ack(s, m, "Attempting to send Jabber Message");
02383    client = ast_aji_get_client(jabber);
02384    if (!client) {
02385       astman_send_error(s, m, "Could not find Sender");
02386       return 0;
02387    }  
02388    if (strchr(screenname, '@') && message){
02389       ast_aji_send(client, screenname, message);   
02390       if (!ast_strlen_zero(id))
02391          astman_append(s, "ActionID: %s\r\n",id);
02392       astman_append(s, "Response: Success\r\n");
02393       return 0;
02394    }
02395    if (!ast_strlen_zero(id))
02396       astman_append(s, "ActionID: %s\r\n",id);
02397    astman_append(s, "Response: Failure\r\n");
02398    return 0;
02399 }

static int reload ( void   )  [static]

Definition at line 2470 of file res_jabber.c.

References aji_reload().

02471 {
02472    aji_reload();
02473    return 0;
02474 }

static int unload_module ( void   )  [static]

Definition at line 2423 of file res_jabber.c.

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

02424 {
02425 
02426    /* Check if TLS is initialized. If that's the case, we can't unload this
02427       module due to a bug in the iksemel library that will cause a crash or
02428       a deadlock. We're trying to find a way to handle this, but in the meantime
02429       we will simply refuse to die... 
02430     */
02431    if (tls_initialized) {
02432       ast_log(LOG_ERROR, "Module can't be unloaded due to a bug in the Iksemel library when using TLS.\n");
02433       return 1;   /* You need a forced unload to get rid of this module */
02434    }
02435 
02436    ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry));
02437    ast_unregister_application(app_ajisend);
02438    ast_unregister_application(app_ajistatus);
02439    ast_manager_unregister("JabberSend");
02440    
02441    ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, {
02442       ASTOBJ_RDLOCK(iterator);
02443       if (option_debug > 2)
02444          ast_log(LOG_DEBUG, "JABBER: Releasing and disconneing client: %s\n", iterator->name);
02445       iterator->state = AJI_DISCONNECTING;
02446       ast_aji_disconnect(iterator);
02447       pthread_join(iterator->thread, NULL);
02448       ASTOBJ_UNLOCK(iterator);
02449    });
02450 
02451    ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy);
02452    ASTOBJ_CONTAINER_DESTROY(&clients);
02453    return 0;
02454 }


Variable Documentation

struct ast_cli_entry aji_cli[] [static]

Definition at line 131 of file res_jabber.c.

char* ajisend_descrip [static]

Initial value:

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

Definition at line 157 of file res_jabber.c.

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

Definition at line 155 of file res_jabber.c.

char* ajistatus_descrip [static]

Definition at line 167 of file res_jabber.c.

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

Definition at line 165 of file res_jabber.c.

char* app_ajisend = "JabberSend" [static]

Definition at line 153 of file res_jabber.c.

char* app_ajistatus = "JabberStatus" [static]

Definition at line 163 of file res_jabber.c.

struct aji_capabilities* capabilities = NULL

Definition at line 176 of file res_jabber.c.

Referenced by 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 2353 of file res_jabber.c.

char no_debug_usage[] [static]

Initial value:

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

Definition at line 118 of file res_jabber.c.

char reload_usage[] [static]

Initial value:

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

Definition at line 122 of file res_jabber.c.

char test_usage[] [static]

Initial value:

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

Definition at line 126 of file res_jabber.c.

int tls_initialized = FALSE [static]

Definition at line 180 of file res_jabber.c.


Generated on Wed Aug 15 01:25:29 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3