A resource for interfacing Asterisk directly as a client or a component to a XMPP/Jabber compliant server. More...
#include "asterisk.h"#include <ctype.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/cli.h"#include "asterisk/app.h"#include "asterisk/pbx.h"#include "asterisk/md5.h"#include "asterisk/acl.h"#include "asterisk/utils.h"#include "asterisk/module.h"#include "asterisk/astobj.h"#include "asterisk/astdb.h"#include "asterisk/manager.h"
Go to the source code of this file.
Defines | |
| #define | JABBER_CONFIG "jabber.conf" |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | acf_jabberstatus_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
| 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) |
| Handle add extra info. | |
| static int | aji_create_buddy (char *label, struct aji_client *client) |
| creates buddy. | |
| static int | aji_create_client (char *label, struct ast_variable *var, int debug) |
| creates aji_client structure. | |
| static int | aji_dinfo_handler (void *data, ikspak *pak) |
| Handler of the return info packet. | |
| static int | aji_ditems_handler (void *data, ikspak *pak) |
| Handles stuff. | |
| static char * | aji_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Reload jabber module. | |
| static char * | aji_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Turn on/off console debugging. | |
| 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) |
| Find the aji_resource we want. | |
| 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) |
| Get the roster of jabber users. | |
| static void | aji_handle_iq (struct aji_client *client, iks *node) |
| Handles. | |
| 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) |
| Check the presence info. | |
| static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
| handles subscription requests. | |
| static int | aji_initialize (struct aji_client *client) |
| prepares client for connect. | |
| static int | aji_io_recv (struct aji_client *client, char *buffer, size_t buf_len, int timeout) |
| Secured or unsecured IO socket receiving function. | |
| static int | aji_is_secure (struct aji_client *client) |
| Tests whether the connection is secured or not. | |
| static int | aji_load_config (int reload) |
| static void | aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming) |
| the debug loop. | |
| static void | aji_pruneregister (struct aji_client *client) |
| goes through roster and prunes users not needed in list, or adds them accordingly. | |
| static int | aji_reconnect (struct aji_client *client) |
| reconnect to jabber server | |
| static int | aji_recv (struct aji_client *client, int timeout) |
| Tries to receive data from the Jabber server. | |
| static void * | aji_recv_loop (void *data) |
| receive message loop. | |
| static int | aji_register_approve_handler (void *data, ikspak *pak) |
| Unknown. | |
| static int | aji_register_query_handler (void *data, ikspak *pak) |
| register handler for incoming querys (IQ's) | |
| static int | aji_reload (int reload) |
| Reload the jabber module. | |
| static int | aji_send_exec (struct ast_channel *chan, void *data) |
| Dial plan function to send a message. | |
| static int | aji_send_header (struct aji_client *client, const char *to) |
| Sends XMPP header to the server. | |
| static int | aji_send_raw (struct aji_client *client, const char *xmlstr) |
| Sends an XML string over an XMPP connection. | |
| static void | aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc) |
| set presence of client. | |
| static char * | aji_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show buddy lists. | |
| static char * | aji_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show client status. | |
| static int | aji_start_sasl (struct aji_client *client, enum ikssasltype type, char *username, char *pass) |
| A wrapper function for iks_start_sasl. | |
| static int | aji_start_tls (struct aji_client *client) |
| Starts the TLS procedure. | |
| 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 char * | aji_test (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Send test message for debugging. | |
| static int | aji_tls_handshake (struct aji_client *client) |
| TLS handshake, OpenSSL initialization. | |
| 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_client * | ast_aji_get_client (const char *name) |
| grab a aji_client structure by label name or JID (without the resource string) | |
| 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, iks *x) |
| Wraps raw sending. | |
| int | ast_aji_send_chat (struct aji_client *client, const char *address, const char *message) |
| sends messages. | |
| static int | gtalk_yuck (iks *node) |
| Jabber GTalk function. | |
| static iks * | jabber_make_auth (iksid *id, const char *pass, const char *sid) |
| Setup the authentication struct. | |
| static int | load_module (void) |
| Unload the jabber module. | |
| 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) |
| Wrapper for aji_reload. | |
| static int | unload_module (void) |
| Unload the jabber module. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct ast_cli_entry | aji_cli [] |
| static char * | app_ajisend = "JabberSend" |
| static char * | app_ajistatus = "JabberStatus" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| struct aji_capabilities * | capabilities = NULL |
| struct aji_client_container | clients |
| static struct ast_flags | globalflags = { AJI_AUTOREGISTER } |
| Global flags, initialized to default values. | |
| static struct ast_custom_function | jabberstatus_function |
| static char | mandescr_jabber_send [] |
A resource for interfacing Asterisk directly as a client or a component to a XMPP/Jabber compliant server.
References:
If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?
Dialplan applications need RETURN variable, like JABBERSENDSTATUS
Definition in file res_jabber.c.
| #define JABBER_CONFIG "jabber.conf" |
Definition at line 173 of file res_jabber.c.
Referenced by aji_load_config().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 3111 of file res_jabber.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 3111 of file res_jabber.c.
| static int acf_jabberstatus_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 489 of file res_jabber.c.
References aji_find_resource(), ast_aji_get_client(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ASTOBJ_CONTAINER_FIND, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_resource::resource, aji_buddy::resources, and aji_resource::status.
00490 { 00491 struct aji_client *client = NULL; 00492 struct aji_buddy *buddy = NULL; 00493 struct aji_resource *r = NULL; 00494 int stat = 7; 00495 AST_DECLARE_APP_ARGS(args, 00496 AST_APP_ARG(sender); 00497 AST_APP_ARG(jid); 00498 ); 00499 AST_DECLARE_APP_ARGS(jid, 00500 AST_APP_ARG(screenname); 00501 AST_APP_ARG(resource); 00502 ); 00503 00504 if (!data) { 00505 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00506 return 0; 00507 } 00508 AST_STANDARD_APP_ARGS(args, data); 00509 00510 if (args.argc != 2) { 00511 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00512 return -1; 00513 } 00514 00515 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00516 00517 if (!(client = ast_aji_get_client(args.sender))) { 00518 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00519 return -1; 00520 } 00521 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00522 if (!buddy) { 00523 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00524 return -1; 00525 } 00526 r = aji_find_resource(buddy, jid.resource); 00527 if (!r && buddy->resources) 00528 r = buddy->resources; 00529 if (!r) 00530 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00531 else 00532 stat = r->status; 00533 snprintf(buf, buflen, "%d", stat); 00534 return 0; 00535 }
| static int aji_act_hook | ( | void * | data, | |
| int | type, | |||
| iks * | node | |||
| ) | [static] |
The action hook parses the inbound packets, constantly running.
| data | aji client structure | |
| type | type of packet | |
| node | the actual packet. |
Definition at line 944 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_is_secure(), aji_recv(), aji_send_header(), aji_send_raw(), aji_start_sasl(), aji_start_tls(), aji_tls_handshake(), asprintf, ast_aji_increment_mid(), ast_aji_send(), ast_debug, ast_free, ast_log(), ast_sha1_hash(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::authorized, aji_client::component, aji_client::f, jabber_make_auth(), aji_client::jid, LOG_ERROR, LOG_WARNING, aji_client::mid, aji_client::password, secret, aji_client::state, aji_client::stream_flags, TRY_SECURE, aji_client::usesasl, and aji_client::usetls.
00945 { 00946 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00947 ikspak *pak = NULL; 00948 iks *auth = NULL; 00949 int features = 0; 00950 00951 if(!node) { 00952 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 00953 ASTOBJ_UNREF(client, aji_client_destroy); 00954 return IKS_HOOK; 00955 } 00956 00957 if (client->state == AJI_DISCONNECTING) { 00958 ASTOBJ_UNREF(client, aji_client_destroy); 00959 return IKS_HOOK; 00960 } 00961 00962 pak = iks_packet(node); 00963 00964 if (!client->component) { /*client */ 00965 switch (type) { 00966 case IKS_NODE_START: 00967 if (client->usetls && !aji_is_secure(client)) { 00968 #ifndef HAVE_OPENSSL 00969 ast_log(LOG_ERROR, "OpenSSL not installed. You need to install OpenSSL on this system, or disable the TLS option in your configuration file\n"); 00970 ASTOBJ_UNREF(client, aji_client_destroy); 00971 return IKS_HOOK; 00972 #else 00973 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 00974 ast_log(LOG_ERROR, "Could not start TLS\n"); 00975 ASTOBJ_UNREF(client, aji_client_destroy); 00976 return IKS_HOOK; 00977 } 00978 #endif 00979 break; 00980 } 00981 if (!client->usesasl) { 00982 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); 00983 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 00984 if (auth) { 00985 iks_insert_attrib(auth, "id", client->mid); 00986 iks_insert_attrib(auth, "to", client->jid->server); 00987 ast_aji_increment_mid(client->mid); 00988 ast_aji_send(client, auth); 00989 iks_delete(auth); 00990 } else 00991 ast_log(LOG_ERROR, "Out of memory.\n"); 00992 } 00993 break; 00994 00995 case IKS_NODE_NORMAL: 00996 #ifdef HAVE_OPENSSL 00997 if (client->stream_flags & TRY_SECURE) { 00998 if (!strcmp("proceed", iks_name(node))) { 00999 return aji_tls_handshake(client); 01000 } 01001 } 01002 #endif 01003 if (!strcmp("stream:features", iks_name(node))) { 01004 features = iks_stream_features(node); 01005 if (client->usesasl) { 01006 if (client->usetls && !aji_is_secure(client)) 01007 break; 01008 if (client->authorized) { 01009 if (features & IKS_STREAM_BIND) { 01010 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); 01011 auth = iks_make_resource_bind(client->jid); 01012 if (auth) { 01013 iks_insert_attrib(auth, "id", client->mid); 01014 ast_aji_increment_mid(client->mid); 01015 ast_aji_send(client, auth); 01016 iks_delete(auth); 01017 } else { 01018 ast_log(LOG_ERROR, "Out of memory.\n"); 01019 break; 01020 } 01021 } 01022 if (features & IKS_STREAM_SESSION) { 01023 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); 01024 auth = iks_make_session(); 01025 if (auth) { 01026 iks_insert_attrib(auth, "id", "auth"); 01027 ast_aji_increment_mid(client->mid); 01028 ast_aji_send(client, auth); 01029 iks_delete(auth); 01030 } else { 01031 ast_log(LOG_ERROR, "Out of memory.\n"); 01032 } 01033 } 01034 } else { 01035 int ret; 01036 if (!client->jid->user) { 01037 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 01038 break; 01039 } 01040 01041 ret = aji_start_sasl(client, features, client->jid->user, client->password); 01042 if (ret != IKS_OK) { 01043 ASTOBJ_UNREF(client, aji_client_destroy); 01044 return IKS_HOOK; 01045 } 01046 break; 01047 } 01048 } 01049 } else if (!strcmp("failure", iks_name(node))) { 01050 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 01051 } else if (!strcmp("success", iks_name(node))) { 01052 client->authorized = 1; 01053 aji_send_header(client, client->jid->server); 01054 } 01055 break; 01056 case IKS_NODE_ERROR: 01057 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01058 ASTOBJ_UNREF(client, aji_client_destroy); 01059 return IKS_HOOK; 01060 break; 01061 case IKS_NODE_STOP: 01062 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01063 ASTOBJ_UNREF(client, aji_client_destroy); 01064 return IKS_HOOK; 01065 break; 01066 } 01067 } else if (client->state != AJI_CONNECTED && client->component) { 01068 switch (type) { 01069 case IKS_NODE_START: 01070 if (client->state == AJI_DISCONNECTED) { 01071 char secret[160], shasum[320], *handshake; 01072 01073 sprintf(secret, "%s%s", pak->id, client->password); 01074 ast_sha1_hash(shasum, secret); 01075 handshake = NULL; 01076 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01077 aji_send_raw(client, handshake); 01078 ast_free(handshake); 01079 handshake = NULL; 01080 } 01081 client->state = AJI_CONNECTING; 01082 if(aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01083 client->state = AJI_CONNECTED; 01084 else 01085 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01086 break; 01087 } 01088 break; 01089 01090 case IKS_NODE_NORMAL: 01091 break; 01092 01093 case IKS_NODE_ERROR: 01094 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01095 ASTOBJ_UNREF(client, aji_client_destroy); 01096 return IKS_HOOK; 01097 01098 case IKS_NODE_STOP: 01099 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01100 ASTOBJ_UNREF(client, aji_client_destroy); 01101 return IKS_HOOK; 01102 } 01103 } 01104 01105 switch (pak->type) { 01106 case IKS_PAK_NONE: 01107 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01108 break; 01109 case IKS_PAK_MESSAGE: 01110 aji_handle_message(client, pak); 01111 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01112 break; 01113 case IKS_PAK_PRESENCE: 01114 aji_handle_presence(client, pak); 01115 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01116 break; 01117 case IKS_PAK_S10N: 01118 aji_handle_subscribe(client, pak); 01119 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01120 break; 01121 case IKS_PAK_IQ: 01122 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01123 aji_handle_iq(client, node); 01124 break; 01125 default: 01126 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01127 break; 01128 } 01129 01130 iks_filter_packet(client->f, pak); 01131 01132 if (node) 01133 iks_delete(node); 01134 01135 ASTOBJ_UNREF(client, aji_client_destroy); 01136 return IKS_OK; 01137 }
| static void aji_buddy_destroy | ( | struct aji_buddy * | obj | ) | [static] |
Deletes the aji_buddy data structure.
| obj | aji_buddy The structure we will delete. |
Definition at line 281 of file res_jabber.c.
References ast_free, aji_resource::description, aji_resource::next, and aji_buddy::resources.
Referenced by aji_client_destroy(), aji_create_buddy(), and aji_handle_presence().
00282 { 00283 struct aji_resource *tmp; 00284 00285 while ((tmp = obj->resources)) { 00286 obj->resources = obj->resources->next; 00287 ast_free(tmp->description); 00288 ast_free(tmp); 00289 } 00290 00291 ast_free(obj); 00292 }
| static int aji_client_connect | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
connects as a client to jabber server.
| data | void | |
| pak | ikspak iksemel packet |
Definition at line 2327 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().
02328 { 02329 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02330 int res = 0; 02331 02332 if (client) { 02333 if (client->state == AJI_DISCONNECTED) { 02334 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); 02335 client->state = AJI_CONNECTING; 02336 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 02337 iks_filter_remove_hook(client->f, aji_client_connect); 02338 if(!client->component) /*client*/ 02339 aji_get_roster(client); 02340 } 02341 } else 02342 ast_log(LOG_ERROR, "Out of memory.\n"); 02343 02344 ASTOBJ_UNREF(client, aji_client_destroy); 02345 return res; 02346 }
| static void aji_client_destroy | ( | struct aji_client * | obj | ) | [static] |
Deletes the aji_client data structure.
| obj | aji_client The structure we will delete. |
Definition at line 257 of file res_jabber.c.
References aji_buddy_destroy(), ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, aji_client::buddies, aji_client::f, aji_message::from, aji_message::list, aji_message::message, aji_client::messages, aji_client::p, and aji_client::stack.
Referenced by aji_act_hook(), aji_client_connect(), aji_client_info_handler(), aji_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().
00258 { 00259 struct aji_message *tmp; 00260 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy); 00261 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00262 iks_filter_delete(obj->f); 00263 iks_parser_delete(obj->p); 00264 iks_stack_delete(obj->stack); 00265 AST_LIST_LOCK(&obj->messages); 00266 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00267 if (tmp->from) 00268 ast_free(tmp->from); 00269 if (tmp->message) 00270 ast_free(tmp->message); 00271 } 00272 AST_LIST_HEAD_DESTROY(&obj->messages); 00273 ast_free(obj); 00274 }
| static int aji_client_info_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Handle add extra info.
| data | void | |
| pak | ikspak |
Definition at line 1353 of file res_jabber.c.
References aji_client_destroy(), aji_find_resource(), ast_aji_send(), 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, and aji_resource::resource.
01354 { 01355 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01356 struct aji_resource *resource = NULL; 01357 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01358 01359 resource = aji_find_resource(buddy, pak->from->resource); 01360 if (pak->subtype == IKS_TYPE_RESULT) { 01361 if (!resource) { 01362 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 01363 ASTOBJ_UNREF(client, aji_client_destroy); 01364 return IKS_FILTER_EAT; 01365 } 01366 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01367 resource->cap->jingle = 1; 01368 } else 01369 resource->cap->jingle = 0; 01370 } else if (pak->subtype == IKS_TYPE_GET) { 01371 iks *iq, *disco, *ident, *google, *query; 01372 iq = iks_new("iq"); 01373 query = iks_new("query"); 01374 ident = iks_new("identity"); 01375 disco = iks_new("feature"); 01376 google = iks_new("feature"); 01377 if (iq && ident && disco && google) { 01378 iks_insert_attrib(iq, "from", client->jid->full); 01379 iks_insert_attrib(iq, "to", pak->from->full); 01380 iks_insert_attrib(iq, "type", "result"); 01381 iks_insert_attrib(iq, "id", pak->id); 01382 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01383 iks_insert_attrib(ident, "category", "client"); 01384 iks_insert_attrib(ident, "type", "pc"); 01385 iks_insert_attrib(ident, "name", "asterisk"); 01386 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 01387 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 01388 iks_insert_node(iq, query); 01389 iks_insert_node(query, ident); 01390 iks_insert_node(query, google); 01391 iks_insert_node(query, disco); 01392 ast_aji_send(client, iq); 01393 } else 01394 ast_log(LOG_ERROR, "Out of Memory.\n"); 01395 01396 iks_delete(iq); 01397 iks_delete(query); 01398 iks_delete(ident); 01399 iks_delete(google); 01400 iks_delete(disco); 01401 } else if (pak->subtype == IKS_TYPE_ERROR) { 01402 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 01403 } 01404 ASTOBJ_UNREF(client, aji_client_destroy); 01405 return IKS_FILTER_EAT; 01406 }
| static int aji_create_buddy | ( | char * | label, | |
| struct aji_client * | client | |||
| ) | [static] |
creates buddy.
| label | char. | |
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 2880 of file res_jabber.c.
References aji_buddy_destroy(), ast_calloc, ast_copy_string(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_LINK, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, LOG_WARNING, and aji_buddy::name.
Referenced by aji_create_client(), aji_handle_presence(), and aji_handle_subscribe().
| static int aji_create_client | ( | char * | label, | |
| struct ast_variable * | var, | |||
| int | debug | |||
| ) | [static] |
creates aji_client structure.
| label | ||
| var | ast_variable | |
| debug |
Definition at line 2660 of file res_jabber.c.
References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_buddy(), AJI_DISCONNECTED, ast_calloc, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::flags, aji_client::forcessl, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, ast_variable::name, aji_client::name, ast_variable::next, aji_client::password, aji_client::port, aji_client::priority, aji_client::serverhost, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and ast_variable::value.
Referenced by aji_load_config().
02661 { 02662 char *resource; 02663 struct aji_client *client = NULL; 02664 int flag = 0; 02665 02666 client = ASTOBJ_CONTAINER_FIND(&clients,label); 02667 if (!client) { 02668 flag = 1; 02669 client = ast_calloc(1, sizeof(*client)); 02670 if (!client) { 02671 ast_log(LOG_ERROR, "Out of memory!\n"); 02672 return 0; 02673 } 02674 ASTOBJ_INIT(client); 02675 ASTOBJ_WRLOCK(client); 02676 ASTOBJ_CONTAINER_INIT(&client->buddies); 02677 } else { 02678 ASTOBJ_WRLOCK(client); 02679 ASTOBJ_UNMARK(client); 02680 } 02681 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 02682 ast_copy_string(client->name, label, sizeof(client->name)); 02683 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 02684 02685 /* Set default values for the client object */ 02686 client->debug = debug; 02687 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 02688 client->port = 5222; 02689 client->usetls = 1; 02690 client->usesasl = 1; 02691 client->forcessl = 0; 02692 client->keepalive = 1; 02693 client->timeout = 50; 02694 client->message_timeout = 100; 02695 AST_LIST_HEAD_INIT(&client->messages); 02696 client->component = 0; 02697 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 02698 client->priority = 0; 02699 client->status = IKS_SHOW_AVAILABLE; 02700 02701 if (flag) { 02702 client->authorized = 0; 02703 client->state = AJI_DISCONNECTED; 02704 } 02705 while (var) { 02706 if (!strcasecmp(var->name, "username")) 02707 ast_copy_string(client->user, var->value, sizeof(client->user)); 02708 else if (!strcasecmp(var->name, "serverhost")) 02709 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 02710 else if (!strcasecmp(var->name, "secret")) 02711 ast_copy_string(client->password, var->value, sizeof(client->password)); 02712 else if (!strcasecmp(var->name, "statusmessage")) 02713 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 02714 else if (!strcasecmp(var->name, "port")) 02715 client->port = atoi(var->value); 02716 else if (!strcasecmp(var->name, "timeout")) 02717 client->message_timeout = atoi(var->value); 02718 else if (!strcasecmp(var->name, "debug")) 02719 client->debug = (ast_false(var->value)) ? 0 : 1; 02720 else if (!strcasecmp(var->name, "type")) { 02721 if (!strcasecmp(var->value, "component")) 02722 client->component = 1; 02723 } else if (!strcasecmp(var->name, "usetls")) { 02724 client->usetls = (ast_false(var->value)) ? 0 : 1; 02725 } else if (!strcasecmp(var->name, "usesasl")) { 02726 client->usesasl = (ast_false(var->value)) ? 0 : 1; 02727 } else if (!strcasecmp(var->name, "forceoldssl")) 02728 client->forcessl = (ast_false(var->value)) ? 0 : 1; 02729 else if (!strcasecmp(var->name, "keepalive")) 02730 client->keepalive = (ast_false(var->value)) ? 0 : 1; 02731 else if (!strcasecmp(var->name, "autoprune")) 02732 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 02733 else if (!strcasecmp(var->name, "autoregister")) 02734 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 02735 else if (!strcasecmp(var->name, "buddy")) 02736 aji_create_buddy((char *)var->value, client); 02737 else if (!strcasecmp(var->name, "priority")) 02738 client->priority = atoi(var->value); 02739 else if (!strcasecmp(var->name, "status")) { 02740 if (!strcasecmp(var->value, "unavailable")) 02741 client->status = IKS_SHOW_UNAVAILABLE; 02742 else 02743 if (!strcasecmp(var->value, "available") 02744 || !strcasecmp(var->value, "online")) 02745 client->status = IKS_SHOW_AVAILABLE; 02746 else 02747 if (!strcasecmp(var->value, "chat") 02748 || !strcasecmp(var->value, "chatty")) 02749 client->status = IKS_SHOW_CHAT; 02750 else 02751 if (!strcasecmp(var->value, "away")) 02752 client->status = IKS_SHOW_AWAY; 02753 else 02754 if (!strcasecmp(var->value, "xa") 02755 || !strcasecmp(var->value, "xaway")) 02756 client->status = IKS_SHOW_XA; 02757 else 02758 if (!strcasecmp(var->value, "dnd")) 02759 client->status = IKS_SHOW_DND; 02760 else 02761 if (!strcasecmp(var->value, "invisible")) 02762 #ifdef IKS_SHOW_INVISIBLE 02763 client->status = IKS_SHOW_INVISIBLE; 02764 #else 02765 { 02766 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 02767 client->status = IKS_SHOW_DND; 02768 } 02769 #endif 02770 else 02771 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 02772 } 02773 /* no transport support in this version */ 02774 /* else if (!strcasecmp(var->name, "transport")) 02775 aji_create_transport(var->value, client); 02776 */ 02777 var = var->next; 02778 } 02779 if (!flag) { 02780 ASTOBJ_UNLOCK(client); 02781 ASTOBJ_UNREF(client, aji_client_destroy); 02782 return 1; 02783 } 02784 02785 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 02786 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 02787 if (!client->p) { 02788 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 02789 return 0; 02790 } 02791 client->stack = iks_stack_new(8192, 8192); 02792 if (!client->stack) { 02793 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 02794 return 0; 02795 } 02796 client->f = iks_filter_new(); 02797 if (!client->f) { 02798 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 02799 return 0; 02800 } 02801 if (!strchr(client->user, '/') && !client->component) { /*client */ 02802 resource = NULL; 02803 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02804 client->jid = iks_id_new(client->stack, resource); 02805 ast_free(resource); 02806 } 02807 } else 02808 client->jid = iks_id_new(client->stack, client->user); 02809 if (client->component) { 02810 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02811 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 02812 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); 02813 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); 02814 } else { 02815 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02816 } 02817 iks_set_log_hook(client->p, aji_log_hook); 02818 ASTOBJ_UNLOCK(client); 02819 ASTOBJ_CONTAINER_LINK(&clients,client); 02820 return 1; 02821 }
| static int aji_dinfo_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Handler of the return info packet.
| data | aji_client | |
| pak | ikspak |
Definition at line 1413 of file res_jabber.c.
References aji_client_destroy(), aji_find_resource(), ast_aji_send(), 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_resource::resource, aji_client::user, and version.
01414 { 01415 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01416 char *node = NULL; 01417 struct aji_resource *resource = NULL; 01418 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01419 01420 resource = aji_find_resource(buddy, pak->from->resource); 01421 if (pak->subtype == IKS_TYPE_ERROR) { 01422 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 01423 return IKS_FILTER_EAT; 01424 } 01425 if (pak->subtype == IKS_TYPE_RESULT) { 01426 if (!resource) { 01427 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); 01428 ASTOBJ_UNREF(client, aji_client_destroy); 01429 return IKS_FILTER_EAT; 01430 } 01431 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01432 resource->cap->jingle = 1; 01433 } else 01434 resource->cap->jingle = 0; 01435 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 01436 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 01437 01438 iq = iks_new("iq"); 01439 query = iks_new("query"); 01440 identity = iks_new("identity"); 01441 disco = iks_new("feature"); 01442 reg = iks_new("feature"); 01443 commands = iks_new("feature"); 01444 gateway = iks_new("feature"); 01445 version = iks_new("feature"); 01446 vcard = iks_new("feature"); 01447 search = iks_new("feature"); 01448 01449 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 01450 iks_insert_attrib(iq, "from", client->user); 01451 iks_insert_attrib(iq, "to", pak->from->full); 01452 iks_insert_attrib(iq, "id", pak->id); 01453 iks_insert_attrib(iq, "type", "result"); 01454 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01455 iks_insert_attrib(identity, "category", "gateway"); 01456 iks_insert_attrib(identity, "type", "pstn"); 01457 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 01458 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 01459 iks_insert_attrib(reg, "var", "jabber:iq:register"); 01460 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 01461 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 01462 iks_insert_attrib(version, "var", "jabber:iq:version"); 01463 iks_insert_attrib(vcard, "var", "vcard-temp"); 01464 iks_insert_attrib(search, "var", "jabber:iq:search"); 01465 01466 iks_insert_node(iq, query); 01467 iks_insert_node(query, identity); 01468 iks_insert_node(query, disco); 01469 iks_insert_node(query, reg); 01470 iks_insert_node(query, commands); 01471 iks_insert_node(query, gateway); 01472 iks_insert_node(query, version); 01473 iks_insert_node(query, vcard); 01474 iks_insert_node(query, search); 01475 ast_aji_send(client, iq); 01476 } else { 01477 ast_log(LOG_ERROR, "Out of memory.\n"); 01478 } 01479 01480 iks_delete(iq); 01481 iks_delete(query); 01482 iks_delete(identity); 01483 iks_delete(disco); 01484 iks_delete(reg); 01485 iks_delete(commands); 01486 iks_delete(gateway); 01487 iks_delete(version); 01488 iks_delete(vcard); 01489 iks_delete(search); 01490 01491 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 01492 iks *iq, *query, *confirm; 01493 iq = iks_new("iq"); 01494 query = iks_new("query"); 01495 confirm = iks_new("item"); 01496 01497 if (iq && query && confirm && client) { 01498 iks_insert_attrib(iq, "from", client->user); 01499 iks_insert_attrib(iq, "to", pak->from->full); 01500 iks_insert_attrib(iq, "id", pak->id); 01501 iks_insert_attrib(iq, "type", "result"); 01502 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01503 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01504 iks_insert_attrib(confirm, "node", "confirmaccount"); 01505 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01506 iks_insert_attrib(confirm, "jid", client->user); 01507 iks_insert_node(iq, query); 01508 iks_insert_node(query, confirm); 01509 ast_aji_send(client, iq); 01510 } else { 01511 ast_log(LOG_ERROR, "Out of memory.\n"); 01512 } 01513 01514 iks_delete(iq); 01515 iks_delete(query); 01516 iks_delete(confirm); 01517 01518 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 01519 iks *iq, *query, *feature; 01520 01521 iq = iks_new("iq"); 01522 query = iks_new("query"); 01523 feature = iks_new("feature"); 01524 01525 if (iq && query && feature && client) { 01526 iks_insert_attrib(iq, "from", client->user); 01527 iks_insert_attrib(iq, "to", pak->from->full); 01528 iks_insert_attrib(iq, "id", pak->id); 01529 iks_insert_attrib(iq, "type", "result"); 01530 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01531 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01532 iks_insert_node(iq, query); 01533 iks_insert_node(query, feature); 01534 ast_aji_send(client, iq); 01535 } else { 01536 ast_log(LOG_ERROR, "Out of memory.\n"); 01537 } 01538 01539 iks_delete(iq); 01540 iks_delete(query); 01541 iks_delete(feature); 01542 } 01543 01544 ASTOBJ_UNREF(client, aji_client_destroy); 01545 return IKS_FILTER_EAT; 01546 }
| static int aji_ditems_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Handles stuff.
| data | void | |
| pak | ikspak |
Definition at line 1258 of file res_jabber.c.
References aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, and aji_client::user.
01259 { 01260 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01261 char *node = NULL; 01262 01263 if (!(node = iks_find_attrib(pak->query, "node"))) { 01264 iks *iq = NULL, *query = NULL, *item = NULL; 01265 iq = iks_new("iq"); 01266 query = iks_new("query"); 01267 item = iks_new("item"); 01268 01269 if (iq && query && item) { 01270 iks_insert_attrib(iq, "from", client->user); 01271 iks_insert_attrib(iq, "to", pak->from->full); 01272 iks_insert_attrib(iq, "id", pak->id); 01273 iks_insert_attrib(iq, "type", "result"); 01274 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01275 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01276 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01277 iks_insert_attrib(item, "jid", client->user); 01278 01279 iks_insert_node(iq, query); 01280 iks_insert_node(query, item); 01281 ast_aji_send(client, iq); 01282 } else { 01283 ast_log(LOG_ERROR, "Out of memory.\n"); 01284 } 01285 01286 iks_delete(iq); 01287 iks_delete(query); 01288 iks_delete(item); 01289 01290 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01291 iks *iq, *query, *confirm; 01292 iq = iks_new("iq"); 01293 query = iks_new("query"); 01294 confirm = iks_new("item"); 01295 if (iq && query && confirm && client) { 01296 iks_insert_attrib(iq, "from", client->user); 01297 iks_insert_attrib(iq, "to", pak->from->full); 01298 iks_insert_attrib(iq, "id", pak->id); 01299 iks_insert_attrib(iq, "type", "result"); 01300 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01301 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01302 iks_insert_attrib(confirm, "node", "confirmaccount"); 01303 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01304 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01305 01306 iks_insert_node(iq, query); 01307 iks_insert_node(query, confirm); 01308 ast_aji_send(client, iq); 01309 } else { 01310 ast_log(LOG_ERROR, "Out of memory.\n"); 01311 } 01312 01313 iks_delete(iq); 01314 iks_delete(query); 01315 iks_delete(confirm); 01316 01317 } else if (!strcasecmp(node, "confirmaccount")) { 01318 iks *iq = NULL, *query = NULL, *feature = NULL; 01319 01320 iq = iks_new("iq"); 01321 query = iks_new("query"); 01322 feature = iks_new("feature"); 01323 01324 if (iq && query && feature && client) { 01325 iks_insert_attrib(iq, "from", client->user); 01326 iks_insert_attrib(iq, "to", pak->from->full); 01327 iks_insert_attrib(iq, "id", pak->id); 01328 iks_insert_attrib(iq, "type", "result"); 01329 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01330 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01331 iks_insert_node(iq, query); 01332 iks_insert_node(query, feature); 01333 ast_aji_send(client, iq); 01334 } else { 01335 ast_log(LOG_ERROR, "Out of memory.\n"); 01336 } 01337 01338 iks_delete(iq); 01339 iks_delete(query); 01340 iks_delete(feature); 01341 } 01342 01343 ASTOBJ_UNREF(client, aji_client_destroy); 01344 return IKS_FILTER_EAT; 01345 01346 }
| static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Reload jabber module.
Definition at line 2482 of file res_jabber.c.
References aji_reload(), ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02483 { 02484 switch (cmd) { 02485 case CLI_INIT: 02486 e->command = "jabber reload"; 02487 e->usage = 02488 "Usage: jabber reload\n" 02489 " Reloads the Jabber module.\n"; 02490 return NULL; 02491 case CLI_GENERATE: 02492 return NULL; 02493 } 02494 02495 aji_reload(1); 02496 ast_cli(a->fd, "Jabber Reloaded.\n"); 02497 return CLI_SUCCESS; 02498 }
| static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Turn on/off console debugging.
Definition at line 2442 of file res_jabber.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02443 { 02444 switch (cmd) { 02445 case CLI_INIT: 02446 e->command = "jabber set debug {on|off}"; 02447 e->usage = 02448 "Usage: jabber set debug {on|off}\n" 02449 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 02450 return NULL; 02451 case CLI_GENERATE: 02452 return NULL; 02453 } 02454 02455 if (a->argc != e->args) 02456 return CLI_SHOWUSAGE; 02457 02458 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 02459 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02460 ASTOBJ_RDLOCK(iterator); 02461 iterator->debug = 1; 02462 ASTOBJ_UNLOCK(iterator); 02463 }); 02464 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02465 return CLI_SUCCESS; 02466 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 02467 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02468 ASTOBJ_RDLOCK(iterator); 02469 iterator->debug = 0; 02470 ASTOBJ_UNLOCK(iterator); 02471 }); 02472 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02473 return CLI_SUCCESS; 02474 } 02475 return CLI_SHOWUSAGE; /* defaults to invalid */ 02476 }
| static int aji_filter_roster | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
filters the roster packet we get back from server.
| data | void | |
| pak | ikspak iksemel packet. |
Definition at line 2200 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, aji_client::flags, and aji_client::state.
Referenced by aji_client_connect().
02201 { 02202 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02203 int flag = 0; 02204 iks *x = NULL; 02205 struct aji_buddy *buddy; 02206 02207 client->state = AJI_CONNECTED; 02208 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02209 ASTOBJ_RDLOCK(iterator); 02210 x = iks_child(pak->query); 02211 flag = 0; 02212 while (x) { 02213 if (!iks_strcmp(iks_name(x), "item")) { 02214 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02215 flag = 1; 02216 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02217 } 02218 } 02219 x = iks_next(x); 02220 } 02221 if (!flag) 02222 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02223 iks_delete(x); 02224 02225 ASTOBJ_UNLOCK(iterator); 02226 }); 02227 02228 x = iks_child(pak->query); 02229 while (x) { 02230 flag = 0; 02231 if (iks_strcmp(iks_name(x), "item") == 0) { 02232 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02233 ASTOBJ_RDLOCK(iterator); 02234 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02235 flag = 1; 02236 ASTOBJ_UNLOCK(iterator); 02237 }); 02238 02239 if (flag) { 02240 /* found buddy, don't create a new one */ 02241 x = iks_next(x); 02242 continue; 02243 } 02244 02245 buddy = ast_calloc(1, sizeof(*buddy)); 02246 if (!buddy) { 02247 ast_log(LOG_WARNING, "Out of memory\n"); 02248 return 0; 02249 } 02250 ASTOBJ_INIT(buddy); 02251 ASTOBJ_WRLOCK(buddy); 02252 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02253 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02254 if(ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02255 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 02256 ASTOBJ_MARK(buddy); 02257 } else if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 02258 /* subscribe to buddy's presence only 02259 if we really need to */ 02260 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 02261 } 02262 ASTOBJ_UNLOCK(buddy); 02263 if (buddy) { 02264 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 02265 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02266 } 02267 } 02268 x = iks_next(x); 02269 } 02270 02271 iks_delete(x); 02272 aji_pruneregister(client); 02273 02274 ASTOBJ_UNREF(client, aji_client_destroy); 02275 return IKS_FILTER_EAT; 02276 }
| static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
| char * | name | |||
| ) | [static, read] |
Find the aji_resource we want.
| buddy | aji_buddy A buddy | |
| name |
Definition at line 370 of file res_jabber.c.
References aji_resource::next, aji_resource::resource, and aji_buddy::resources.
Referenced by acf_jabberstatus_read(), aji_client_info_handler(), aji_dinfo_handler(), and aji_status_exec().
| 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.
| 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 | struct The XML stanza we're processing |
Definition at line 303 of file res_jabber.c.
References ast_copy_string(), ast_free, ast_log(), ast_malloc, aji_version::jingle, LOG_ERROR, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::parent, aji_version::version, and aji_capabilities::versions.
Referenced by aji_handle_presence().
00304 { 00305 struct aji_capabilities *list = NULL; 00306 struct aji_version *res = NULL; 00307 00308 list = capabilities; 00309 00310 if(!node) 00311 node = pak->from->full; 00312 if(!version) 00313 version = "none supplied."; 00314 while(list) { 00315 if(!strcasecmp(list->node, node)) { 00316 res = list->versions; 00317 while(res) { 00318 if(!strcasecmp(res->version, version)) 00319 return res; 00320 res = res->next; 00321 } 00322 /* Specified version not found. Let's add it to 00323 this node in our capabilities list */ 00324 if(!res) { 00325 res = ast_malloc(sizeof(*res)); 00326 if(!res) { 00327 ast_log(LOG_ERROR, "Out of memory!\n"); 00328 return NULL; 00329 } 00330 res->jingle = 0; 00331 res->parent = list; 00332 ast_copy_string(res->version, version, sizeof(res->version)); 00333 res->next = list->versions; 00334 list->versions = res; 00335 return res; 00336 } 00337 } 00338 list = list->next; 00339 } 00340 /* Specified node not found. Let's add it our capabilities list */ 00341 if(!list) { 00342 list = ast_malloc(sizeof(*list)); 00343 if(!list) { 00344 ast_log(LOG_ERROR, "Out of memory!\n"); 00345 return NULL; 00346 } 00347 res = ast_malloc(sizeof(*res)); 00348 if(!res) { 00349 ast_log(LOG_ERROR, "Out of memory!\n"); 00350 ast_free(list); 00351 return NULL; 00352 } 00353 ast_copy_string(list->node, node, sizeof(list->node)); 00354 ast_copy_string(res->version, version, sizeof(res->version)); 00355 res->jingle = 0; 00356 res->parent = list; 00357 res->next = NULL; 00358 list->versions = res; 00359 list->next = capabilities; 00360 capabilities = list; 00361 } 00362 return res; 00363 }
| static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Get the roster of jabber users.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 2305 of file res_jabber.c.
References aji_set_presence(), ast_aji_send(), aji_client::jid, aji_client::status, and aji_client::statusmessage.
Referenced by aji_client_connect(), and aji_reload().
02306 { 02307 iks *roster = NULL; 02308 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 02309 02310 if(roster) { 02311 iks_insert_attrib(roster, "id", "roster"); 02312 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 02313 ast_aji_send(client, roster); 02314 } 02315 02316 iks_delete(roster); 02317 02318 return 1; 02319 }
| static void aji_handle_iq | ( | struct aji_client * | client, | |
| iks * | node | |||
| ) | [static] |
Handles.
<iq>
tags.
| client | the configured XMPP client we use to connect to a XMPP server | |
| node | iks |
Definition at line 1554 of file res_jabber.c.
Referenced by aji_act_hook().
| static void aji_handle_message | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Handles presence packets.
| client | the configured XMPP client we use to connect to a XMPP server | |
| pak | ikspak the node |
Definition at line 1564 of file res_jabber.c.
References aji_message::arrived, ast_calloc, ast_copy_string(), ast_free, 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, aji_message::from, aji_message::id, aji_message::list, aji_message::message, aji_client::message_timeout, and aji_client::messages.
Referenced by aji_act_hook().
01565 { 01566 struct aji_message *insert, *tmp; 01567 int flag = 0; 01568 01569 if (!(insert = ast_calloc(1, sizeof(*insert)))) 01570 return; 01571 time(&insert->arrived); 01572 if (iks_find_cdata(pak->x, "body")) 01573 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 01574 if (pak->id) 01575 ast_copy_string(insert->id, pak->id, sizeof(insert->message)); 01576 if (pak->from) 01577 insert->from = ast_strdup(pak->from->full); 01578 AST_LIST_LOCK(&client->messages); 01579 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 01580 if (flag) { 01581 AST_LIST_REMOVE_CURRENT(list); 01582 if (tmp->from) 01583 ast_free(tmp->from); 01584 if (tmp->message) 01585 ast_free(tmp->message); 01586 } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) { 01587 flag = 1; 01588 AST_LIST_REMOVE_CURRENT(list); 01589 if (tmp->from) 01590 ast_free(tmp->from); 01591 if (tmp->message) 01592 ast_free(tmp->message); 01593 } 01594 } 01595 AST_LIST_TRAVERSE_SAFE_END; 01596 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 01597 AST_LIST_UNLOCK(&client->messages); 01598 }
| static void aji_handle_presence | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Check the presence info.
| client | the configured XMPP client we use to connect to a XMPP server | |
| pak | ikspak |
Definition at line 1604 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_aji_send(), ast_calloc, ast_copy_string(), ast_debug, ast_free, 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, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, aji_client::mid, aji_resource::next, option_debug, aji_resource::priority, aji_resource::resource, aji_buddy::resources, aji_client::state, aji_resource::status, aji_client::status, status, aji_client::statusmessage, type, and ver.
Referenced by aji_act_hook().
01605 { 01606 int status, priority; 01607 struct aji_buddy *buddy; 01608 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 01609 char *ver, *node, *descrip, *type; 01610 01611 if(client->state != AJI_CONNECTED) 01612 aji_create_buddy(pak->from->partial, client); 01613 01614 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01615 if (!buddy && pak->from->partial) { 01616 /* allow our jid to be used to log in with another resource */ 01617 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 01618 aji_create_buddy(pak->from->partial, client); 01619 else 01620 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 01621 return; 01622 } 01623 type = iks_find_attrib(pak->x, "type"); 01624 if(client->component && type &&!strcasecmp("probe", type)) { 01625 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01626 ast_verbose("what i was looking for \n"); 01627 } 01628 ASTOBJ_WRLOCK(buddy); 01629 status = (pak->show) ? pak->show : 6; 01630 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 01631 tmp = buddy->resources; 01632 descrip = ast_strdup(iks_find_cdata(pak->x,"status")); 01633 01634 while (tmp && pak->from->resource) { 01635 if (!strcasecmp(tmp->resource, pak->from->resource)) { 01636 tmp->status = status; 01637 if (tmp->description) ast_free(tmp->description); 01638 tmp->description = descrip; 01639 found = tmp; 01640 if (status == 6) { /* Sign off Destroy resource */ 01641 if (last && found->next) { 01642 last->next = found->next; 01643 } else if (!last) { 01644 if (found->next) 01645 buddy->resources = found->next; 01646 else 01647 buddy->resources = NULL; 01648 } else if (!found->next) { 01649 if (last) 01650 last->next = NULL; 01651 else 01652 buddy->resources = NULL; 01653 } 01654 ast_free(found); 01655 found = NULL; 01656 break; 01657 } 01658 /* resource list is sorted by descending priority */ 01659 if (tmp->priority != priority) { 01660 found->priority = priority; 01661 if (!last && !found->next) 01662 /* resource was found to be unique, 01663 leave loop */ 01664 break; 01665 /* search for resource in our list 01666 and take it out for the moment */ 01667 if (last) 01668 last->next = found->next; 01669 else 01670 buddy->resources = found->next; 01671 01672 last = NULL; 01673 tmp = buddy->resources; 01674 if (!buddy->resources) 01675 buddy->resources = found; 01676 /* priority processing */ 01677 while (tmp) { 01678 /* insert resource back according to 01679 its priority value */ 01680 if (found->priority > tmp->priority) { 01681 if (last) 01682 /* insert within list */ 01683 last->next = found; 01684 found->next = tmp; 01685 if (!last) 01686 /* insert on top */ 01687 buddy->resources = found; 01688 break; 01689 } 01690 if (!tmp->next) { 01691 /* insert at the end of the list */ 01692 tmp->next = found; 01693 found->next = NULL; 01694 break; 01695 } 01696 last = tmp; 01697 tmp = tmp->next; 01698 } 01699 } 01700 break; 01701 } 01702 last = tmp; 01703 tmp = tmp->next; 01704 } 01705 01706 /* resource not found in our list, create it */ 01707 if (!found && status != 6 && pak->from->resource) { 01708 found = ast_calloc(1, sizeof(*found)); 01709 01710 if (!found) { 01711 ast_log(LOG_ERROR, "Out of memory!\n"); 01712 return; 01713 } 01714 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 01715 found->status = status; 01716 found->description = descrip; 01717 found->priority = priority; 01718 found->next = NULL; 01719 last = NULL; 01720 tmp = buddy->resources; 01721 while (tmp) { 01722 if (found->priority > tmp->priority) { 01723 if (last) 01724 last->next = found; 01725 found->next = tmp; 01726 if (!last) 01727 buddy->resources = found; 01728 break; 01729 } 01730 if (!tmp->next) { 01731 tmp->next = found; 01732 break; 01733 } 01734 last = tmp; 01735 tmp = tmp->next; 01736 } 01737 if (!tmp) 01738 buddy->resources = found; 01739 } 01740 01741 ASTOBJ_UNLOCK(buddy); 01742 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 01743 01744 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 01745 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 01746 01747 /* handle gmail client's special caps:c tag */ 01748 if (!node && !ver) { 01749 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 01750 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 01751 } 01752 01753 /* retrieve capabilites of the new resource */ 01754 if(status !=6 && found && !found->cap) { 01755 found->cap = aji_find_version(node, ver, pak); 01756 if(gtalk_yuck(pak->x)) /* gtalk should do discover */ 01757 found->cap->jingle = 1; 01758 if(found->cap->jingle && option_debug > 4) { 01759 ast_debug(1,"Special case for google till they support discover.\n"); 01760 } 01761 else { 01762 iks *iq, *query; 01763 iq = iks_new("iq"); 01764 query = iks_new("query"); 01765 if(query && iq) { 01766 iks_insert_attrib(iq, "type", "get"); 01767 iks_insert_attrib(iq, "to", pak->from->full); 01768 iks_insert_attrib(iq,"from", client->jid->full); 01769 iks_insert_attrib(iq, "id", client->mid); 01770 ast_aji_increment_mid(client->mid); 01771 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01772 iks_insert_node(iq, query); 01773 ast_aji_send(client, iq); 01774 01775 } else 01776 ast_log(LOG_ERROR, "Out of memory.\n"); 01777 01778 iks_delete(query); 01779 iks_delete(iq); 01780 } 01781 } 01782 switch (pak->subtype) { 01783 case IKS_TYPE_AVAILABLE: 01784 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 01785 break; 01786 case IKS_TYPE_UNAVAILABLE: 01787 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 01788 break; 01789 default: 01790 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 01791 } 01792 switch (pak->show) { 01793 case IKS_SHOW_UNAVAILABLE: 01794 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01795 break; 01796 case IKS_SHOW_AVAILABLE: 01797 ast_debug(3, "JABBER: type is available\n"); 01798 break; 01799 case IKS_SHOW_CHAT: 01800 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01801 break; 01802 case IKS_SHOW_AWAY: 01803 ast_debug(3, "JABBER: type is away\n"); 01804 break; 01805 case IKS_SHOW_XA: 01806 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01807 break; 01808 case IKS_SHOW_DND: 01809 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01810 break; 01811 default: 01812 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 01813 } 01814 }
| static void aji_handle_subscribe | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
handles subscription requests.
| client | the configured XMPP client we use to connect to a XMPP server | |
| pak | ikspak iksemel packet. |
Definition at line 1822 of file res_jabber.c.
References aji_create_buddy(), aji_set_presence(), ast_aji_send(), ast_log(), ast_verbose, ASTOBJ_CONTAINER_FIND, aji_client::buddies, aji_client::component, aji_client::jid, LOG_ERROR, option_verbose, aji_client::status, status, aji_client::statusmessage, and VERBOSE_PREFIX_3.
Referenced by aji_act_hook().
01823 { 01824 iks *presence = NULL, *status = NULL; 01825 struct aji_buddy* buddy = NULL; 01826 01827 switch (pak->subtype) { 01828 case IKS_TYPE_SUBSCRIBE: 01829 presence = iks_new("presence"); 01830 status = iks_new("status"); 01831 if (presence && status) { 01832 iks_insert_attrib(presence, "type", "subscribed"); 01833 iks_insert_attrib(presence, "to", pak->from->full); 01834 iks_insert_attrib(presence, "from", client->jid->full); 01835 if (pak->id) 01836 iks_insert_attrib(presence, "id", pak->id); 01837 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 01838 iks_insert_node(presence, status); 01839 ast_aji_send(client, presence); 01840 } else 01841 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 01842 01843 iks_delete(presence); 01844 iks_delete(status); 01845 01846 if (client->component) 01847 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01848 case IKS_TYPE_SUBSCRIBED: 01849 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01850 if (!buddy && pak->from->partial) { 01851 aji_create_buddy(pak->from->partial, client); 01852 } 01853 default: 01854 if (option_verbose > 4) { 01855 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 01856 } 01857 } 01858 }
| static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
prepares client for connect.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 2353 of file res_jabber.c.
References ast_log(), aji_client::component, connected, aji_client::jid, LOG_ERROR, aji_client::name, aji_client::p, aji_client::port, S_OR, aji_client::serverhost, aji_client::stream_flags, and aji_client::user.
Referenced by aji_reconnect().
02354 { 02355 int connected = IKS_NET_NOCONN; 02356 02357 #ifdef HAVE_OPENSSL 02358 /* reset stream flags */ 02359 client->stream_flags = 0; 02360 #endif 02361 /* If it's a component, connect to user, otherwise, connect to server */ 02362 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 02363 02364 if (connected == IKS_NET_NOCONN) { 02365 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 02366 return IKS_HOOK; 02367 } else if (connected == IKS_NET_NODNS) { 02368 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server)); 02369 return IKS_HOOK; 02370 } 02371 02372 return IKS_OK; 02373 }
| static int aji_io_recv | ( | struct aji_client * | client, | |
| char * | buffer, | |||
| size_t | buf_len, | |||
| int | timeout | |||
| ) | [static] |
Secured or unsecured IO socket receiving function.
| client | the configured XMPP client we use to connect to a XMPP server | |
| buffer | the reception buffer | |
| buf_len | the size of the buffer | |
| timeout | the select timer |
Definition at line 669 of file res_jabber.c.
References aji_is_secure(), ast_select(), len(), aji_client::p, and aji_client::ssl_session.
Referenced by aji_recv().
00670 { 00671 int sock; 00672 fd_set fds; 00673 struct timeval tv, *tvptr = NULL; 00674 int len, res; 00675 00676 #ifdef HAVE_OPENSSL 00677 if (aji_is_secure(client)) { 00678 sock = SSL_get_fd(client->ssl_session); 00679 if (sock < 0) 00680 return -1; 00681 } else 00682 #endif /* HAVE_OPENSSL */ 00683 sock = iks_fd(client->p); 00684 00685 memset(&tv, 0, sizeof(struct timeval)); 00686 FD_ZERO(&fds); 00687 FD_SET(sock, &fds); 00688 tv.tv_sec = timeout; 00689 00690 /* NULL value for tvptr makes ast_select wait indefinitely */ 00691 tvptr = (timeout != -1) ? &tv : NULL; 00692 00693 /* ast_select emulates linux behaviour in terms of timeout handling */ 00694 res = ast_select(sock + 1, &fds, NULL, NULL, tvptr); 00695 if (res > 0) { 00696 #ifdef HAVE_OPENSSL 00697 if (aji_is_secure(client)) { 00698 len = SSL_read(client->ssl_session, buffer, buf_len); 00699 } else 00700 #endif /* HAVE_OPENSSL */ 00701 len = recv(sock, buffer, buf_len, 0); 00702 00703 if (len > 0) { 00704 return len; 00705 } else if (len <= 0) { 00706 return -1; 00707 } 00708 } 00709 return res; 00710 }
| static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Tests whether the connection is secured or not.
Definition at line 583 of file res_jabber.c.
References SECURE, and aji_client::stream_flags.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
00584 { 00585 #ifdef HAVE_OPENSSL 00586 return client->stream_flags & SECURE; 00587 #else 00588 return 0; 00589 #endif 00590 }
| static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 2907 of file res_jabber.c.
References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, debug, JABBER_CONFIG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by aji_reload().
02908 { 02909 char *cat = NULL; 02910 int debug = 1; 02911 struct ast_config *cfg = NULL; 02912 struct ast_variable *var = NULL; 02913 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02914 02915 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 02916 return -1; 02917 02918 /* Reset flags to default value */ 02919 ast_set_flag(&globalflags, AJI_AUTOREGISTER); 02920 02921 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 02922 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 02923 return 0; 02924 } 02925 02926 cat = ast_category_browse(cfg, NULL); 02927 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 02928 if (!strcasecmp(var->name, "debug")) { 02929 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 02930 } else if (!strcasecmp(var->name, "autoprune")) { 02931 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 02932 } else if (!strcasecmp(var->name, "autoregister")) { 02933 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 02934 } 02935 } 02936 02937 while (cat) { 02938 if (strcasecmp(cat, "general")) { 02939 var = ast_variable_browse(cfg, cat); 02940 aji_create_client(cat, var, debug); 02941 } 02942 cat = ast_category_browse(cfg, cat); 02943 } 02944 ast_config_destroy(cfg); /* or leak memory */ 02945 return 1; 02946 }
| static void aji_log_hook | ( | void * | data, | |
| const char * | xmpp, | |||
| size_t | size, | |||
| int | is_incoming | |||
| ) | [static] |
the debug loop.
| data | void | |
| xmpp | xml data as string | |
| size | size of string | |
| is_incoming | direction of packet 1 for inbound 0 for outbound. |
Definition at line 863 of file res_jabber.c.
References aji_client_destroy(), ast_strlen_zero(), ast_verbose, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::debug, EVENT_FLAG_USER, manager_event, aji_client::name, and option_debug.
Referenced by aji_recv(), and aji_send_raw().
00864 { 00865 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00866 00867 if (!ast_strlen_zero(xmpp)) 00868 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 00869 00870 if (client->debug) { 00871 if (is_incoming) 00872 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 00873 else { 00874 if( strlen(xmpp) == 1) { 00875 if(option_debug > 2 && xmpp[0] == ' ') { 00876 ast_verbose("\nJABBER: Keep alive packet\n"); 00877 } 00878 } else 00879 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 00880 } 00881 00882 } 00883 ASTOBJ_UNREF(client, aji_client_destroy); 00884 }
| static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
goes through roster and prunes users not needed in list, or adds them accordingly.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 2146 of file res_jabber.c.
References AJI_AUTOPRUNE, ast_aji_send(), ast_log(), ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, aji_client::buddies, aji_client::jid, and LOG_ERROR.
02147 { 02148 int res = 0; 02149 iks *removeiq = iks_new("iq"); 02150 iks *removequery = iks_new("query"); 02151 iks *removeitem = iks_new("item"); 02152 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02153 if (!client || !removeiq || !removequery || !removeitem || !send) { 02154 ast_log(LOG_ERROR, "Out of memory.\n"); 02155 goto safeout; 02156 } 02157 02158 iks_insert_node(removeiq, removequery); 02159 iks_insert_node(removequery, removeitem); 02160 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02161 ASTOBJ_RDLOCK(iterator); 02162 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02163 * be called at the same time */ 02164 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02165 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02166 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02167 " so I am no longer subscribing to your presence.\n")); 02168 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02169 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02170 " your access to my presence.\n")); 02171 iks_insert_attrib(removeiq, "from", client->jid->full); 02172 iks_insert_attrib(removeiq, "type", "set"); 02173 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02174 iks_insert_attrib(removeitem, "jid", iterator->name); 02175 iks_insert_attrib(removeitem, "subscription", "remove"); 02176 res = ast_aji_send(client, removeiq); 02177 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02178 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02179 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02180 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02181 } 02182 ASTOBJ_UNLOCK(iterator); 02183 }); 02184 02185 safeout: 02186 iks_delete(removeiq); 02187 iks_delete(removequery); 02188 iks_delete(removeitem); 02189 iks_delete(send); 02190 02191 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); 02192 }
| static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
reconnect to jabber server
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 2283 of file res_jabber.c.
References AJI_DISCONNECTED, aji_initialize(), aji_client::authorized, aji_client::p, aji_client::state, and aji_client::timeout.
Referenced by aji_recv_loop().
02284 { 02285 int res = 0; 02286 02287 if (client->state) 02288 client->state = AJI_DISCONNECTED; 02289 client->timeout=50; 02290 if (client->p) 02291 iks_parser_reset(client->p); 02292 if (client->authorized) 02293 client->authorized = 0; 02294 02295 res = aji_initialize(client); 02296 02297 return res; 02298 }
| static int aji_recv | ( | struct aji_client * | client, | |
| int | timeout | |||
| ) | [static] |
Tries to receive data from the Jabber server.
| client | the configured XMPP client we use to connect to a XMPP server | |
| timeout | the timeout value This function receives (encrypted or unencrypted) data from the XMPP server, and passes it to the parser. |
Definition at line 721 of file res_jabber.c.
References aji_io_recv(), aji_log_hook(), ast_debug, ast_log(), buf, IKS_NET_EXPIRED, len(), LOG_WARNING, NET_IO_BUF_SIZE, and aji_client::p.
Referenced by aji_act_hook(), and aji_recv_loop().
00722 { 00723 int len, ret; 00724 char buf[NET_IO_BUF_SIZE - 1]; 00725 char newbuf[NET_IO_BUF_SIZE - 1]; 00726 int pos = 0; 00727 int newbufpos = 0; 00728 unsigned char c; 00729 00730 memset(buf, 0, sizeof(buf)); 00731 memset(newbuf, 0, sizeof(newbuf)); 00732 00733 while (1) { 00734 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 00735 if (len < 0) return IKS_NET_RWERR; 00736 if (len == 0) return IKS_NET_EXPIRED; 00737 buf[len] = '\0'; 00738 00739 /* our iksemel parser won't work as expected if we feed 00740 it with XML packets that contain multiple whitespace 00741 characters between tags */ 00742 while (pos < len) { 00743 c = buf[pos]; 00744 /* if we stumble on the ending tag character, 00745 we skip any whitespace that follows it*/ 00746 if (c == '>') { 00747 while (isspace(buf[pos+1])) { 00748 pos++; 00749 } 00750 } 00751 newbuf[newbufpos] = c; 00752 newbufpos ++; 00753 pos++; 00754 } 00755 pos = 0; 00756 newbufpos = 0; 00757 00758 /* Log the message here, because iksemel's logHook is 00759 unaccessible */ 00760 aji_log_hook(client, buf, len, 1); 00761 00762 /* let iksemel deal with the string length, 00763 and reset our buffer */ 00764 ret = iks_parse(client->p, newbuf, 0, 0); 00765 memset(newbuf, 0, sizeof(newbuf)); 00766 00767 switch (ret) { 00768 case IKS_NOMEM: 00769 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 00770 break; 00771 case IKS_BADXML: 00772 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 00773 break; 00774 case IKS_HOOK: 00775 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 00776 break; 00777 } 00778 if (ret != IKS_OK) { 00779 return ret; 00780 } 00781 ast_debug(3, "XML parsing successful\n"); 00782 } 00783 return IKS_OK; 00784 }
| static void * aji_recv_loop | ( | void * | data | ) | [static] |
receive message loop.
| data | void |
Definition at line 1985 of file res_jabber.c.
References aji_client_destroy(), AJI_CONNECTED, AJI_DISCONNECTING, aji_reconnect(), aji_recv(), aji_send_raw(), ast_debug, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, IKS_NET_EXPIRED, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::state, and aji_client::timeout.
Referenced by aji_reload().
01986 { 01987 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01988 int res = IKS_HOOK; 01989 01990 while(res != IKS_OK) { 01991 ast_debug(3, "JABBER: Connecting.\n"); 01992 res = aji_reconnect(client); 01993 sleep(4); 01994 } 01995 01996 do { 01997 if (res == IKS_NET_RWERR || client->timeout == 0) { 01998 while(res != IKS_OK) { 01999 ast_debug(3, "JABBER: reconnecting.\n"); 02000 res = aji_reconnect(client); 02001 sleep(4); 02002 } 02003 } 02004 02005 res = aji_recv(client, 1); 02006 02007 if (client->state == AJI_DISCONNECTING) { 02008 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02009 pthread_exit(NULL); 02010 } 02011 02012 /* Decrease timeout if no data received */ 02013 if (res == IKS_NET_EXPIRED) 02014 client->timeout--; 02015 02016 if (res == IKS_HOOK) 02017 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02018 else if (res == IKS_NET_TLSFAIL) 02019 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02020 else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02021 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02022 if(res == IKS_OK) 02023 client->timeout = 50; 02024 else 02025 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02026 } else if (res == IKS_NET_RWERR) 02027 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02028 } while (client); 02029 ASTOBJ_UNREF(client, aji_client_destroy); 02030 return 0; 02031 }
| static int aji_register_approve_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Unknown.
| data | void | |
| pak | ikspak |
Definition at line 1144 of file res_jabber.c.
References aji_client_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::jid, LOG_ERROR, and aji_client::mid.
01145 { 01146 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01147 iks *iq = NULL, *presence = NULL, *x = NULL; 01148 01149 iq = iks_new("iq"); 01150 presence = iks_new("presence"); 01151 x = iks_new("x"); 01152 if (client && iq && presence && x) { 01153 if (!iks_find(pak->query, "remove")) { 01154 iks_insert_attrib(iq, "from", client->jid->full); 01155 iks_insert_attrib(iq, "to", pak->from->full); 01156 iks_insert_attrib(iq, "id", pak->id); 01157 iks_insert_attrib(iq, "type", "result"); 01158 ast_aji_send(client, iq); 01159 01160 iks_insert_attrib(presence, "from", client->jid->full); 01161 iks_insert_attrib(presence, "to", pak->from->partial); 01162 iks_insert_attrib(presence, "id", client->mid); 01163 ast_aji_increment_mid(client->mid); 01164 iks_insert_attrib(presence, "type", "subscribe"); 01165 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01166 iks_insert_node(presence, x); 01167 ast_aji_send(client, presence); 01168 } 01169 } else { 01170 ast_log(LOG_ERROR, "Out of memory.\n"); 01171 } 01172 01173 01174 iks_delete(iq); 01175 iks_delete(presence); 01176 iks_delete(x); 01177 01178 ASTOBJ_UNREF(client, aji_client_destroy); 01179 return IKS_FILTER_EAT; 01180 }
| static int aji_register_query_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
register handler for incoming querys (IQ's)
| data | incoming aji_client request | |
| pak | ikspak |
Definition at line 1187 of file res_jabber.c.
References aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, LOG_ERROR, and aji_client::user.
01188 { 01189 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01190 struct aji_buddy *buddy = NULL; 01191 char *node = NULL; 01192 iks *iq = NULL, *query = NULL; 01193 01194 client = (struct aji_client *) data; 01195 01196 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01197 if (!buddy) { 01198 iks *error = NULL, *notacceptable = NULL; 01199 01200 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01201 iq = iks_new("iq"); 01202 query = iks_new("query"); 01203 error = iks_new("error"); 01204 notacceptable = iks_new("not-acceptable"); 01205 if(iq && query && error && notacceptable) { 01206 iks_insert_attrib(iq, "type", "error"); 01207 iks_insert_attrib(iq, "from", client->user); 01208 iks_insert_attrib(iq, "to", pak->from->full); 01209 iks_insert_attrib(iq, "id", pak->id); 01210 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01211 iks_insert_attrib(error, "code" , "406"); 01212 iks_insert_attrib(error, "type", "modify"); 01213 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01214 iks_insert_node(iq, query); 01215 iks_insert_node(iq, error); 01216 iks_insert_node(error, notacceptable); 01217 ast_aji_send(client, iq); 01218 } else { 01219 ast_log(LOG_ERROR, "Out of memory.\n"); 01220 } 01221 01222 iks_delete(error); 01223 iks_delete(notacceptable); 01224 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01225 iks *instructions = NULL; 01226 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01227 iq = iks_new("iq"); 01228 query = iks_new("query"); 01229 instructions = iks_new("instructions"); 01230 if (iq && query && instructions && client) { 01231 iks_insert_attrib(iq, "from", client->user); 01232 iks_insert_attrib(iq, "to", pak->from->full); 01233 iks_insert_attrib(iq, "id", pak->id); 01234 iks_insert_attrib(iq, "type", "result"); 01235 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01236 iks_insert_cdata(instructions, explain, 0); 01237 iks_insert_node(iq, query); 01238 iks_insert_node(query, instructions); 01239 ast_aji_send(client, iq); 01240 } else { 01241 ast_log(LOG_ERROR, "Out of memory.\n"); 01242 } 01243 01244 iks_delete(instructions); 01245 } 01246 iks_delete(iq); 01247 iks_delete(query); 01248 ASTOBJ_UNREF(client, aji_client_destroy); 01249 return IKS_FILTER_EAT; 01250 }
| static int aji_reload | ( | int | reload | ) | [static] |
Reload the jabber module.
Definition at line 3035 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().
03036 { 03037 int res; 03038 03039 ASTOBJ_CONTAINER_MARKALL(&clients); 03040 if (!(res = aji_load_config(reload))) { 03041 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 03042 return 0; 03043 } else if (res == -1) 03044 return 1; 03045 03046 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); 03047 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03048 ASTOBJ_RDLOCK(iterator); 03049 if(iterator->state == AJI_DISCONNECTED) { 03050 if (!iterator->thread) 03051 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 03052 } else if (iterator->state == AJI_CONNECTING) 03053 aji_get_roster(iterator); 03054 ASTOBJ_UNLOCK(iterator); 03055 }); 03056 03057 return 1; 03058 }
| static int aji_send_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Dial plan function to send a message.
| chan | ast_channel | |
| data | Data is sender|receiver|message. |
Definition at line 548 of file res_jabber.c.
References ast_aji_get_client(), ast_aji_send_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), LOG_ERROR, LOG_WARNING, and s.
Referenced by load_module().
00549 { 00550 struct aji_client *client = NULL; 00551 char *s; 00552 AST_DECLARE_APP_ARGS(args, 00553 AST_APP_ARG(sender); 00554 AST_APP_ARG(recipient); 00555 AST_APP_ARG(message); 00556 ); 00557 00558 if (!data) { 00559 ast_log(LOG_ERROR, "Usage: JabberSend(<sender>,<recipient>,<message>)\n"); 00560 return 0; 00561 } 00562 s = ast_strdupa(data); 00563 00564 AST_STANDARD_APP_ARGS(args, s); 00565 if (args.argc < 3) { 00566 ast_log(LOG_ERROR, "JabberSend requires 3 arguments: '%s'\n", (char *) data); 00567 return -1; 00568 } 00569 00570 if (!(client = ast_aji_get_client(args.sender))) { 00571 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00572 return -1; 00573 } 00574 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) 00575 ast_aji_send_chat(client, args.recipient, args.message); 00576 return 0; 00577 }
| static int aji_send_header | ( | struct aji_client * | client, | |
| const char * | to | |||
| ) | [static] |
Sends XMPP header to the server.
| client | the configured XMPP client we use to connect to a XMPP server | |
| to | the target XMPP server |
Definition at line 792 of file res_jabber.c.
References aji_send_raw(), len(), msg, and aji_client::name_space.
Referenced by aji_act_hook(), and aji_tls_handshake().
00793 { 00794 char *msg; 00795 int len, err; 00796 00797 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 00798 msg = iks_malloc(len); 00799 if (!msg) 00800 return IKS_NOMEM; 00801 sprintf(msg, "<?xml version='1.0'?>" 00802 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 00803 "%s' to='%s' version='1.0'>", client->name_space, to); 00804 err = aji_send_raw(client, msg); 00805 iks_free(msg); 00806 if (err != IKS_OK) 00807 return err; 00808 00809 return IKS_OK; 00810 }
| static int aji_send_raw | ( | struct aji_client * | client, | |
| const char * | xmlstr | |||
| ) | [static] |
Sends an XML string over an XMPP connection.
| client | the configured XMPP client we use to connect to a XMPP server | |
| xmlstr | the XML string to send The XML data is sent whether the connection is secured or not. In the latter case, we just call iks_send_raw(). |
Definition at line 831 of file res_jabber.c.
References aji_is_secure(), aji_log_hook(), len(), aji_client::p, and aji_client::ssl_session.
Referenced by aji_act_hook(), aji_recv_loop(), aji_send_header(), and ast_aji_send().
00832 { 00833 int ret; 00834 #ifdef HAVE_OPENSSL 00835 int len = strlen(xmlstr); 00836 00837 if (aji_is_secure(client)) { 00838 ret = SSL_write(client->ssl_session, xmlstr, len); 00839 if (ret) { 00840 /* Log the message here, because iksemel's logHook is 00841 unaccessible */ 00842 aji_log_hook(client, xmlstr, len, 0); 00843 return IKS_OK; 00844 } 00845 } 00846 #endif 00847 /* If needed, data will be sent unencrypted, and logHook will 00848 be called inside iks_send_raw */ 00849 ret = iks_send_raw(client->p, xmlstr); 00850 if (ret != IKS_OK) 00851 return ret; 00852 00853 return IKS_OK; 00854 }
| static void aji_set_presence | ( | struct aji_client * | client, | |
| char * | to, | |||
| char * | from, | |||
| int | level, | |||
| char * | desc | |||
| ) | [static] |
set presence of client.
| client | the configured XMPP client we use to connect to a XMPP server | |
| to | user send it to | |
| from | user it came from | |
| level | ||
| desc |
Definition at line 2408 of file res_jabber.c.
References ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::priority.
Referenced by aji_get_roster(), aji_handle_presence(), and aji_handle_subscribe().
02409 { 02410 int res = 0; 02411 iks *presence = iks_make_pres(level, desc); 02412 iks *cnode = iks_new("c"); 02413 iks *priority = iks_new("priority"); 02414 char priorityS[10]; 02415 02416 if (presence && cnode && client && priority) { 02417 if(to) 02418 iks_insert_attrib(presence, "to", to); 02419 if(from) 02420 iks_insert_attrib(presence, "from", from); 02421 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 02422 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 02423 iks_insert_node(presence, priority); 02424 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 02425 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 02426 iks_insert_attrib(cnode, "ext", "voice-v1"); 02427 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 02428 iks_insert_node(presence, cnode); 02429 res = ast_aji_send(client, presence); 02430 } else 02431 ast_log(LOG_ERROR, "Out of memory.\n"); 02432 02433 iks_delete(cnode); 02434 iks_delete(presence); 02435 iks_delete(priority); 02436 }
| static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show buddy lists.
Definition at line 2549 of file res_jabber.c.
References ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, aji_client::buddies, aji_resource::cap, CLI_GENERATE, CLI_INIT, clients, ast_cli_entry::command, ast_cli_args::fd, aji_version::jingle, aji_resource::next, aji_capabilities::node, aji_version::parent, aji_resource::priority, aji_resource::resource, aji_resource::status, ast_cli_entry::usage, and aji_version::version.
02550 { 02551 struct aji_resource *resource; 02552 struct aji_client *client; 02553 02554 switch (cmd) { 02555 case CLI_INIT: 02556 e->command = "jabber show buddies"; 02557 e->usage = 02558 "Usage: jabber show buddies\n" 02559 " Shows buddy lists of our clients\n"; 02560 return NULL; 02561 case CLI_GENERATE: 02562 return NULL; 02563 } 02564 02565 ast_cli(a->fd, "Jabber buddy lists\n"); 02566 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02567 ast_cli(a->fd,"Client: %s\n", iterator->user); 02568 client = iterator; 02569 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02570 ASTOBJ_RDLOCK(iterator); 02571 ast_cli(a->fd,"\tBuddy:\t%s\n", iterator->name); 02572 if (!iterator->resources) 02573 ast_cli(a->fd,"\t\tResource: None\n"); 02574 for (resource = iterator->resources; resource; resource = resource->next) { 02575 ast_cli(a->fd,"\t\tResource: %s\n", resource->resource); 02576 if(resource->cap) { 02577 ast_cli(a->fd,"\t\t\tnode: %s\n", resource->cap->parent->node); 02578 ast_cli(a->fd,"\t\t\tversion: %s\n", resource->cap->version); 02579 ast_cli(a->fd,"\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 02580 } 02581 ast_cli(a->fd,"\t\tStatus: %d\n", resource->status); 02582 ast_cli(a->fd,"\t\tPriority: %d\n", resource->priority); 02583 } 02584 ASTOBJ_UNLOCK(iterator); 02585 }); 02586 iterator = client; 02587 }); 02588 return CLI_SUCCESS; 02589 }
| static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show client status.
Definition at line 2504 of file res_jabber.c.
References AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.
02505 { 02506 char *status; 02507 int count = 0; 02508 02509 switch (cmd) { 02510 case CLI_INIT: 02511 e->command = "jabber show connected"; 02512 e->usage = 02513 "Usage: jabber show connected\n" 02514 " Shows state of clients and components\n"; 02515 return NULL; 02516 case CLI_GENERATE: 02517 return NULL; 02518 } 02519 02520 ast_cli(a->fd, "Jabber Users and their status:\n"); 02521 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02522 ASTOBJ_RDLOCK(iterator); 02523 count++; 02524 switch (iterator->state) { 02525 case AJI_DISCONNECTED: 02526 status = "Disconnected"; 02527 break; 02528 case AJI_CONNECTING: 02529 status = "Connecting"; 02530 break; 02531 case AJI_CONNECTED: 02532 status = "Connected"; 02533 break; 02534 default: 02535 status = "Unknown"; 02536 } 02537 ast_cli(a->fd, " User: %s - %s\n", iterator->user, status); 02538 ASTOBJ_UNLOCK(iterator); 02539 }); 02540 ast_cli(a->fd, "----\n"); 02541 ast_cli(a->fd, " Number of users: %d\n", count); 02542 return CLI_SUCCESS; 02543 }
| static int aji_start_sasl | ( | struct aji_client * | client, | |
| enum ikssasltype | type, | |||
| char * | username, | |||
| char * | pass | |||
| ) | [static] |
A wrapper function for iks_start_sasl.
| client | the configured XMPP client we use to connect to a XMPP server | |
| type | the SASL authentication type. Supported types are PLAIN and MD5 | |
| username | ||
| pass | password. |
Definition at line 895 of file res_jabber.c.
References aji_is_secure(), ast_aji_send(), ast_base64encode(), ast_log(), base64, len(), LOG_ERROR, aji_client::p, and s.
Referenced by aji_act_hook().
00896 { 00897 iks *x = NULL; 00898 int len; 00899 char *s; 00900 char *base64; 00901 00902 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 00903 iks_start_sasl is an iksemel API function and relies on GnuTLS, 00904 whereas we use OpenSSL */ 00905 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 00906 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 00907 if (!(type & IKS_STREAM_SASL_PLAIN)) { 00908 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 00909 return IKS_NET_NOTSUPP; 00910 } 00911 00912 x = iks_new("auth"); 00913 if (!x) { 00914 ast_log(LOG_ERROR, "Out of memory.\n"); 00915 return IKS_NET_NOTSUPP; 00916 } 00917 00918 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 00919 len = strlen(username) + strlen(pass) + 3; 00920 s = alloca(len); 00921 base64 = alloca((len + 2) * 4 / 3); 00922 iks_insert_attrib(x, "mechanism", "PLAIN"); 00923 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 00924 00925 /* exclude the NULL training byte from the base64 encoding operation 00926 as some XMPP servers will refuse it. 00927 The format for authentication is [authzid]\0authcid\0password 00928 not [authzid]\0authcid\0password\0 */ 00929 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 00930 iks_insert_cdata(x, base64, 0); 00931 ast_aji_send(client, x); 00932 iks_delete(x); 00933 00934 return IKS_OK; 00935 }
| static int aji_start_tls | ( | struct aji_client * | client | ) | [static] |
Starts the TLS procedure.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 599 of file res_jabber.c.
References aji_client::p, aji_client::stream_flags, and TRY_SECURE.
Referenced by aji_act_hook().
00600 { 00601 int ret; 00602 00603 /* This is sent not encrypted */ 00604 ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); 00605 if (ret) 00606 return ret; 00607 00608 client->stream_flags |= TRY_SECURE; 00609 return IKS_OK; 00610 }
| 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.
| chan | ast_channel | |
| data |
Definition at line 432 of file res_jabber.c.
References aji_find_resource(), ast_aji_get_client(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, 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 status.
Referenced by load_module().
00433 { 00434 struct aji_client *client = NULL; 00435 struct aji_buddy *buddy = NULL; 00436 struct aji_resource *r = NULL; 00437 char *s = NULL; 00438 int stat = 7; 00439 char status[2]; 00440 static int deprecation_warning = 0; 00441 AST_DECLARE_APP_ARGS(args, 00442 AST_APP_ARG(sender); 00443 AST_APP_ARG(jid); 00444 AST_APP_ARG(variable); 00445 ); 00446 AST_DECLARE_APP_ARGS(jid, 00447 AST_APP_ARG(screenname); 00448 AST_APP_ARG(resource); 00449 ); 00450 00451 if (deprecation_warning++ % 10 == 0) 00452 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00453 00454 if (!data) { 00455 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00456 return 0; 00457 } 00458 s = ast_strdupa(data); 00459 AST_STANDARD_APP_ARGS(args, s); 00460 00461 if (args.argc != 3) { 00462 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00463 return -1; 00464 } 00465 00466 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00467 00468 if (!(client = ast_aji_get_client(args.sender))) { 00469 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00470 return -1; 00471 } 00472 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00473 if (!buddy) { 00474 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00475 return -1; 00476 } 00477 r = aji_find_resource(buddy, jid.resource); 00478 if (!r && buddy->resources) 00479 r = buddy->resources; 00480 if (!r) 00481 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00482 else 00483 stat = r->status; 00484 snprintf(status, sizeof(status), "%d", stat); 00485 pbx_builtin_setvar_helper(chan, args.variable, status); 00486 return 0; 00487 }
| static char * aji_test | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send test message for debugging.
Definition at line 2595 of file res_jabber.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_aji_send_chat(), ast_cli(), ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, aji_client::buddies, aji_resource::cap, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, clients, ast_cli_entry::command, aji_resource::description, ast_cli_args::fd, aji_version::jingle, name, aji_resource::next, aji_capabilities::node, aji_version::parent, aji_resource::priority, aji_resource::resource, S_OR, aji_resource::status, ast_cli_entry::usage, and aji_version::version.
02596 { 02597 struct aji_client *client; 02598 struct aji_resource *resource; 02599 const char *name = "asterisk"; 02600 struct aji_message *tmp; 02601 02602 switch (cmd) { 02603 case CLI_INIT: 02604 e->command = "jabber test"; 02605 e->usage = 02606 "Usage: jabber test [client]\n" 02607 " Sends test message for debugging purposes. A specific client\n" 02608 " as configured in jabber.conf can be optionally specified.\n"; 02609 return NULL; 02610 case CLI_GENERATE: 02611 return NULL; 02612 } 02613 02614 if (a->argc > 3) 02615 return CLI_SHOWUSAGE; 02616 else if (a->argc == 3) 02617 name = a->argv[2]; 02618 02619 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 02620 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 02621 return CLI_FAILURE; 02622 } 02623 02624 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 02625 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 02626 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02627 ASTOBJ_RDLOCK(iterator); 02628 ast_verbose("User: %s\n", iterator->name); 02629 for (resource = iterator->resources; resource; resource = resource->next) { 02630 ast_verbose("Resource: %s\n", resource->resource); 02631 if(resource->cap) { 02632 ast_verbose(" client: %s\n", resource->cap->parent->node); 02633 ast_verbose(" version: %s\n", resource->cap->version); 02634 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 02635 } 02636 ast_verbose(" Priority: %d\n", resource->priority); 02637 ast_verbose(" Status: %d\n", resource->status); 02638 ast_verbose(" Message: %s\n", S_OR(resource->description,"")); 02639 } 02640 ASTOBJ_UNLOCK(iterator); 02641 }); 02642 ast_verbose("\nOooh a working message stack!\n"); 02643 AST_LIST_LOCK(&client->messages); 02644 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 02645 ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 02646 } 02647 AST_LIST_UNLOCK(&client->messages); 02648 ASTOBJ_UNREF(client, aji_client_destroy); 02649 02650 return CLI_SUCCESS; 02651 }
| static int aji_tls_handshake | ( | struct aji_client * | client | ) | [static] |
TLS handshake, OpenSSL initialization.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 617 of file res_jabber.c.
References aji_send_header(), ast_debug, aji_client::jid, aji_client::p, SECURE, aji_client::ssl_context, aji_client::ssl_method, aji_client::ssl_session, aji_client::stream_flags, and TRY_SECURE.
Referenced by aji_act_hook().
00618 { 00619 int ret; 00620 int sock; 00621 00622 ast_debug(1, "Starting TLS handshake\n"); 00623 00624 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 00625 client->ssl_method = SSLv3_method(); 00626 client->ssl_context = SSL_CTX_new(client->ssl_method); 00627 if (!client->ssl_context) 00628 return IKS_NET_TLSFAIL; 00629 00630 /* Create new SSL session */ 00631 client->ssl_session = SSL_new(client->ssl_context); 00632 if (!client->ssl_session) 00633 return IKS_NET_TLSFAIL; 00634 00635 /* Enforce TLS on our XMPP connection */ 00636 sock = iks_fd(client->p); 00637 ret = SSL_set_fd(client->ssl_session, sock); 00638 if (!ret) 00639 return IKS_NET_TLSFAIL; 00640 00641 /* Perform SSL handshake */ 00642 ret = SSL_connect(client->ssl_session); 00643 if (!ret) 00644 return IKS_NET_TLSFAIL; 00645 00646 client->stream_flags &= (~TRY_SECURE); 00647 client->stream_flags |= SECURE; 00648 00649 /* Sent over the established TLS connection */ 00650 ret = aji_send_header(client, client->jid->server); 00651 if (ret != IKS_OK) 00652 return IKS_NET_TLSFAIL; 00653 00654 ast_debug(1, "TLS started with server\n"); 00655 00656 return IKS_OK; 00657 }
| int ast_aji_create_chat | ( | struct aji_client * | client, | |
| char * | room, | |||
| char * | server, | |||
| char * | topic | |||
| ) |
create a chatroom.
| client | the configured XMPP client we use to connect to a XMPP server | |
| room | name of room | |
| server | name of server | |
| topic | topic for the room. |
Definition at line 1894 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01895 { 01896 int res = 0; 01897 iks *iq = NULL; 01898 iq = iks_new("iq"); 01899 01900 if (iq && client) { 01901 iks_insert_attrib(iq, "type", "get"); 01902 iks_insert_attrib(iq, "to", server); 01903 iks_insert_attrib(iq, "id", client->mid); 01904 ast_aji_increment_mid(client->mid); 01905 ast_aji_send(client, iq); 01906 } else 01907 ast_log(LOG_ERROR, "Out of memory.\n"); 01908 01909 iks_delete(iq); 01910 01911 return res; 01912 }
| int ast_aji_disconnect | ( | struct aji_client * | client | ) |
disconnect from jabber server.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 2380 of file res_jabber.c.
References aji_client_destroy(), ast_verb, ASTOBJ_UNREF, aji_client::p, SECURE, aji_client::ssl_context, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by unload_module().
02381 { 02382 if (client) { 02383 ast_verb(4, "JABBER: Disconnecting\n"); 02384 #ifdef HAVE_OPENSSL 02385 if (client->stream_flags & SECURE) { 02386 SSL_shutdown(client->ssl_session); 02387 SSL_CTX_free(client->ssl_context); 02388 SSL_free(client->ssl_session); 02389 } 02390 #endif 02391 iks_disconnect(client->p); 02392 iks_parser_delete(client->p); 02393 ASTOBJ_UNREF(client, aji_client_destroy); 02394 } 02395 02396 return 1; 02397 }
| struct aji_client* ast_aji_get_client | ( | const char * | name | ) | [read] |
grab a aji_client structure by label name or JID (without the resource string)
| name | label or JID |
Definition at line 2954 of file res_jabber.c.
References ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, and clients.
Referenced by acf_jabberstatus_read(), aji_send_exec(), aji_status_exec(), gtalk_create_member(), gtalk_newcall(), gtalk_request(), jingle_create_member(), jingle_newcall(), jingle_request(), and manager_jabber_send().
02955 { 02956 struct aji_client *client = NULL; 02957 char *aux = NULL; 02958 02959 client = ASTOBJ_CONTAINER_FIND(&clients, name); 02960 if (!client && strchr(name, '@')) { 02961 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02962 aux = ast_strdupa(iterator->user); 02963 if (strchr(aux, '/')) { 02964 /* strip resource for comparison */ 02965 aux = strsep(&aux, "/"); 02966 } 02967 if (!strncasecmp(aux, name, strlen(aux))) { 02968 client = iterator; 02969 } 02970 }); 02971 } 02972 02973 return client; 02974 }
| struct aji_client_container* ast_aji_get_clients | ( | void | ) | [read] |
Definition at line 2976 of file res_jabber.c.
References clients.
Referenced by gtalk_load_config(), and jingle_load_config().
02977 { 02978 return &clients; 02979 }
| void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
| mid | char. |
Definition at line 2038 of file res_jabber.c.
Referenced by aji_act_hook(), aji_handle_presence(), aji_register_approve_handler(), ast_aji_create_chat(), ast_aji_invite_chat(), gtalk_action(), gtalk_create_candidates(), gtalk_digit(), gtalk_invite(), gtalk_invite_response(), jingle_accept_call(), jingle_action(), jingle_create_candidates(), jingle_digit(), and jingle_transmit_invite().
| int ast_aji_invite_chat | ( | struct aji_client * | client, | |
| char * | user, | |||
| char * | room, | |||
| char * | message | |||
| ) |
invite to a chatroom.
| client | the configured XMPP client we use to connect to a XMPP server | |
| user | ||
| room | ||
| message |
Definition at line 1951 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01952 { 01953 int res = 0; 01954 iks *invite, *body, *namespace; 01955 01956 invite = iks_new("message"); 01957 body = iks_new("body"); 01958 namespace = iks_new("x"); 01959 if (client && invite && body && namespace) { 01960 iks_insert_attrib(invite, "to", user); 01961 iks_insert_attrib(invite, "id", client->mid); 01962 ast_aji_increment_mid(client->mid); 01963 iks_insert_cdata(body, message, 0); 01964 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 01965 iks_insert_attrib(namespace, "jid", room); 01966 iks_insert_node(invite, body); 01967 iks_insert_node(invite, namespace); 01968 res = ast_aji_send(client, invite); 01969 } else 01970 ast_log(LOG_ERROR, "Out of memory.\n"); 01971 01972 iks_delete(body); 01973 iks_delete(namespace); 01974 iks_delete(invite); 01975 01976 return res; 01977 }
| int ast_aji_join_chat | ( | struct aji_client * | client, | |
| char * | room | |||
| ) |
join a chatroom.
| client | the configured XMPP client we use to connect to a XMPP server | |
| room | room to join |
Definition at line 1920 of file res_jabber.c.
References ast_aji_send(), ast_log(), and LOG_ERROR.
01921 { 01922 int res = 0; 01923 iks *presence = NULL, *priority = NULL; 01924 presence = iks_new("presence"); 01925 priority = iks_new("priority"); 01926 if (presence && priority && client) { 01927 iks_insert_cdata(priority, "0", 1); 01928 iks_insert_attrib(presence, "to", room); 01929 iks_insert_node(presence, priority); 01930 res = ast_aji_send(client, presence); 01931 iks_insert_cdata(priority, "5", 1); 01932 iks_insert_attrib(presence, "to", room); 01933 res = ast_aji_send(client, presence); 01934 } else 01935 ast_log(LOG_ERROR, "Out of memory.\n"); 01936 01937 iks_delete(presence); 01938 iks_delete(priority); 01939 01940 return res; 01941 }
| int ast_aji_send | ( | struct aji_client * | client, | |
| iks * | x | |||
| ) |
Wraps raw sending.
| client | the configured XMPP client we use to connect to a XMPP server | |
| x | the XMPP packet to send |
Definition at line 818 of file res_jabber.c.
References aji_send_raw().
Referenced by aji_act_hook(), aji_client_info_handler(), aji_dinfo_handler(), aji_ditems_handler(), aji_get_roster(), aji_handle_presence(), aji_handle_subscribe(), aji_pruneregister(), aji_register_approve_handler(), aji_register_query_handler(), aji_set_presence(), aji_start_sasl(), ast_aji_create_chat(), ast_aji_invite_chat(), ast_aji_join_chat(), ast_aji_send_chat(), gtalk_action(), gtalk_add_candidate(), gtalk_create_candidates(), gtalk_digit(), gtalk_invite(), gtalk_invite_response(), gtalk_response(), jingle_accept_call(), jingle_action(), jingle_add_candidate(), jingle_create_candidates(), jingle_digit(), jingle_response(), and jingle_transmit_invite().
00819 { 00820 return aji_send_raw(client, iks_string(iks_stack(x), x)); 00821 }
| int ast_aji_send_chat | ( | struct aji_client * | client, | |
| const char * | address, | |||
| const char * | message | |||
| ) |
sends messages.
| client | the configured XMPP client we use to connect to a XMPP server | |
| address | ||
| message |
Definition at line 1867 of file res_jabber.c.
References AJI_CONNECTED, ast_aji_send(), ast_log(), aji_client::jid, LOG_ERROR, LOG_WARNING, and aji_client::state.
Referenced by aji_send_exec(), aji_test(), and manager_jabber_send().
01868 { 01869 int res = 0; 01870 iks *message_packet = NULL; 01871 if (client->state == AJI_CONNECTED) { 01872 message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message); 01873 if (message_packet) { 01874 iks_insert_attrib(message_packet, "from", client->jid->full); 01875 res = ast_aji_send(client, message_packet); 01876 } else { 01877 ast_log(LOG_ERROR, "Out of memory.\n"); 01878 } 01879 01880 iks_delete(message_packet); 01881 } else 01882 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 01883 return 1; 01884 }
| static int gtalk_yuck | ( | iks * | node | ) | [static] |
Jabber GTalk function.
| node | iks |
Definition at line 390 of file res_jabber.c.
Referenced by aji_handle_presence().
| static iks * jabber_make_auth | ( | iksid * | id, | |
| const char * | pass, | |||
| const char * | sid | |||
| ) | [static] |
Setup the authentication struct.
| id | iksid | |
| pass | password | |
| sid |
Definition at line 404 of file res_jabber.c.
References ast_sha1_hash(), and buf.
Referenced by aji_act_hook().
00405 { 00406 iks *x, *y; 00407 x = iks_new("iq"); 00408 iks_insert_attrib(x, "type", "set"); 00409 y = iks_insert(x, "query"); 00410 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00411 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00412 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00413 if (sid) { 00414 char buf[41]; 00415 char sidpass[100]; 00416 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00417 ast_sha1_hash(buf, sidpass); 00418 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00419 } else { 00420 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00421 } 00422 return x; 00423 }
| static int load_module | ( | void | ) | [static] |
Unload the jabber module.
Definition at line 3085 of file res_jabber.c.
References aji_reload(), aji_send_exec(), aji_status_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_manager_register2(), AST_MODULE_LOAD_DECLINE, ast_register_application_xml, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, and manager_jabber_send().
03086 { 03087 ASTOBJ_CONTAINER_INIT(&clients); 03088 if(!aji_reload(0)) 03089 return AST_MODULE_LOAD_DECLINE; 03090 ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, 03091 "Sends a message to a Jabber Client", mandescr_jabber_send); 03092 ast_register_application_xml(app_ajisend, aji_send_exec); 03093 ast_register_application_xml(app_ajistatus, aji_status_exec); 03094 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 03095 ast_custom_function_register(&jabberstatus_function); 03096 03097 return 0; 03098 }
| static int manager_jabber_send | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send a Jabber Message via call from the Manager.
| s | mansession Manager session | |
| m | message Message to send |
Definition at line 2994 of file res_jabber.c.
References ast_aji_get_client(), ast_aji_send_chat(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by load_module().
02995 { 02996 struct aji_client *client = NULL; 02997 const char *id = astman_get_header(m,"ActionID"); 02998 const char *jabber = astman_get_header(m,"Jabber"); 02999 const char *screenname = astman_get_header(m,"ScreenName"); 03000 const char *message = astman_get_header(m,"Message"); 03001 03002 if (ast_strlen_zero(jabber)) { 03003 astman_send_error(s, m, "No transport specified"); 03004 return 0; 03005 } 03006 if (ast_strlen_zero(screenname)) { 03007 astman_send_error(s, m, "No ScreenName specified"); 03008 return 0; 03009 } 03010 if (ast_strlen_zero(message)) { 03011 astman_send_error(s, m, "No Message specified"); 03012 return 0; 03013 } 03014 03015 astman_send_ack(s, m, "Attempting to send Jabber Message"); 03016 client = ast_aji_get_client(jabber); 03017 if (!client) { 03018 astman_send_error(s, m, "Could not find Sender"); 03019 return 0; 03020 } 03021 if (strchr(screenname, '@') && message) { 03022 ast_aji_send_chat(client, screenname, message); 03023 astman_append(s, "Response: Success\r\n"); 03024 } else { 03025 astman_append(s, "Response: Error\r\n"); 03026 } 03027 if (!ast_strlen_zero(id)) { 03028 astman_append(s, "ActionID: %s\r\n",id); 03029 } 03030 astman_append(s, "\r\n"); 03031 return 0; 03032 }
| static int reload | ( | void | ) | [static] |
Wrapper for aji_reload.
Definition at line 3101 of file res_jabber.c.
References aji_reload().
03102 { 03103 aji_reload(1); 03104 return 0; 03105 }
| static int unload_module | ( | void | ) | [static] |
Unload the jabber module.
Definition at line 3061 of file res_jabber.c.
References aji_client_destroy(), AJI_DISCONNECTING, ARRAY_LEN, ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_debug, ast_manager_unregister(), ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and clients.
03062 { 03063 03064 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 03065 ast_unregister_application(app_ajisend); 03066 ast_unregister_application(app_ajistatus); 03067 ast_manager_unregister("JabberSend"); 03068 ast_custom_function_unregister(&jabberstatus_function); 03069 03070 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03071 ASTOBJ_RDLOCK(iterator); 03072 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 03073 iterator->state = AJI_DISCONNECTING; 03074 ast_aji_disconnect(iterator); 03075 pthread_join(iterator->thread, NULL); 03076 ASTOBJ_UNLOCK(iterator); 03077 }); 03078 03079 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); 03080 ASTOBJ_CONTAINER_DESTROY(&clients); 03081 return 0; 03082 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3111 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
Definition at line 234 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 242 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 244 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3111 of file res_jabber.c.
| struct aji_capabilities* capabilities = NULL |
Definition at line 247 of file res_jabber.c.
Referenced by ast_request().
| struct aji_client_container clients |
Definition at line 246 of file res_jabber.c.
Referenced by aji_create_client(), aji_do_set_debug(), aji_reload(), aji_show_buddies(), aji_show_clients(), aji_test(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), jingle_load_config(), load_module(), and unload_module().
struct ast_flags globalflags = { AJI_AUTOREGISTER } [static] |
Global flags, initialized to default values.
Definition at line 250 of file res_jabber.c.
struct ast_custom_function jabberstatus_function [static] |
{
.name = "JABBER_STATUS",
.read = acf_jabberstatus_read,
}
Definition at line 537 of file res_jabber.c.
char mandescr_jabber_send[] [static] |
Definition at line 2981 of file res_jabber.c.
1.6.2