#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 | FALSE 0 |
#define | JABBER_CONFIG "jabber.conf" |
#define | TRUE 1 |
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_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Turn on/off console debugging (deprecated, use aji_do_set_debug). | |
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. | |
aji_client * | ast_aji_get_client (const char *name) |
grab a aji_client structure by label name or JID (without the resource string) | |
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct ast_cli_entry | aji_cli [] |
static char * | ajisend_descrip |
static char * | ajisend_synopsis = "JabberSend(jabber,screenname,message)" |
static char * | ajistatus_descrip |
static char * | ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)" |
static char * | app_ajisend = "JabberSend" |
static char * | app_ajistatus = "JabberStatus" |
static struct ast_module_info * | ast_module_info = &__mod_info |
aji_capabilities * | capabilities = NULL |
static struct ast_cli_entry | cli_aji_do_debug_deprecated = { .handler = aji_do_debug_deprecated , .summary = "Enable/disable jabber debugging" ,__VA_ARGS__ } |
aji_client_container | clients |
static struct ast_flags | globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER } |
Global flags, initialized to default values. | |
static struct ast_custom_function | jabberstatus_function |
static char | mandescr_jabber_send [] |
References:
Dialplan applications need RETURN variable, like JABBERSENDSTATUS
Definition in file res_jabber.c.
#define FALSE 0 |
Definition at line 67 of file res_jabber.c.
#define JABBER_CONFIG "jabber.conf" |
Definition at line 64 of file res_jabber.c.
Referenced by aji_load_config().
#define TRUE 1 |
Definition at line 71 of file res_jabber.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 3078 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 3078 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 401 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.
00402 { 00403 struct aji_client *client = NULL; 00404 struct aji_buddy *buddy = NULL; 00405 struct aji_resource *r = NULL; 00406 int stat = 7; 00407 AST_DECLARE_APP_ARGS(args, 00408 AST_APP_ARG(sender); 00409 AST_APP_ARG(jid); 00410 ); 00411 AST_DECLARE_APP_ARGS(jid, 00412 AST_APP_ARG(screenname); 00413 AST_APP_ARG(resource); 00414 ); 00415 00416 if (!data) { 00417 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00418 return 0; 00419 } 00420 AST_STANDARD_APP_ARGS(args, data); 00421 00422 if (args.argc != 2) { 00423 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00424 return -1; 00425 } 00426 00427 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00428 00429 if (!(client = ast_aji_get_client(args.sender))) { 00430 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00431 return -1; 00432 } 00433 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00434 if (!buddy) { 00435 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00436 return -1; 00437 } 00438 r = aji_find_resource(buddy, jid.resource); 00439 if (!r && buddy->resources) 00440 r = buddy->resources; 00441 if (!r) 00442 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00443 else 00444 stat = r->status; 00445 snprintf(buf, buflen, "%d", stat); 00446 return 0; 00447 }
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 864 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::usesasl, and aji_client::usetls.
Referenced by aji_create_client().
00865 { 00866 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00867 ikspak *pak = NULL; 00868 iks *auth = NULL; 00869 int features = 0; 00870 00871 if(!node) { 00872 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 00873 ASTOBJ_UNREF(client, aji_client_destroy); 00874 return IKS_HOOK; 00875 } 00876 00877 if (client->state == AJI_DISCONNECTING) { 00878 ASTOBJ_UNREF(client, aji_client_destroy); 00879 return IKS_HOOK; 00880 } 00881 00882 pak = iks_packet(node); 00883 00884 if (!client->component) { /*client */ 00885 switch (type) { 00886 case IKS_NODE_START: 00887 if (client->usetls && !aji_is_secure(client)) { 00888 #ifndef HAVE_OPENSSL 00889 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"); 00890 ASTOBJ_UNREF(client, aji_client_destroy); 00891 return IKS_HOOK; 00892 #else 00893 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 00894 ast_log(LOG_ERROR, "Could not start TLS\n"); 00895 ASTOBJ_UNREF(client, aji_client_destroy); 00896 return IKS_HOOK; 00897 } 00898 #endif 00899 break; 00900 } 00901 if (!client->usesasl) { 00902 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); 00903 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 00904 if (auth) { 00905 iks_insert_attrib(auth, "id", client->mid); 00906 iks_insert_attrib(auth, "to", client->jid->server); 00907 ast_aji_increment_mid(client->mid); 00908 ast_aji_send(client, auth); 00909 iks_delete(auth); 00910 } else 00911 ast_log(LOG_ERROR, "Out of memory.\n"); 00912 } 00913 break; 00914 00915 case IKS_NODE_NORMAL: 00916 #ifdef HAVE_OPENSSL 00917 if (client->stream_flags & TRY_SECURE) { 00918 if (!strcmp("proceed", iks_name(node))) { 00919 return aji_tls_handshake(client); 00920 } 00921 } 00922 #endif 00923 if (!strcmp("stream:features", iks_name(node))) { 00924 features = iks_stream_features(node); 00925 if (client->usesasl) { 00926 if (client->usetls && !aji_is_secure(client)) 00927 break; 00928 if (client->authorized) { 00929 if (features & IKS_STREAM_BIND) { 00930 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); 00931 auth = iks_make_resource_bind(client->jid); 00932 if (auth) { 00933 iks_insert_attrib(auth, "id", client->mid); 00934 ast_aji_increment_mid(client->mid); 00935 ast_aji_send(client, auth); 00936 iks_delete(auth); 00937 } else { 00938 ast_log(LOG_ERROR, "Out of memory.\n"); 00939 break; 00940 } 00941 } 00942 if (features & IKS_STREAM_SESSION) { 00943 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); 00944 auth = iks_make_session(); 00945 if (auth) { 00946 iks_insert_attrib(auth, "id", "auth"); 00947 ast_aji_increment_mid(client->mid); 00948 ast_aji_send(client, auth); 00949 iks_delete(auth); 00950 } else { 00951 ast_log(LOG_ERROR, "Out of memory.\n"); 00952 } 00953 } 00954 } else { 00955 int ret; 00956 if (!client->jid->user) { 00957 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 00958 break; 00959 } 00960 00961 ret = aji_start_sasl(client, features, client->jid->user, client->password); 00962 if (ret != IKS_OK) { 00963 ASTOBJ_UNREF(client, aji_client_destroy); 00964 return IKS_HOOK; 00965 } 00966 break; 00967 } 00968 } 00969 } else if (!strcmp("failure", iks_name(node))) { 00970 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 00971 } else if (!strcmp("success", iks_name(node))) { 00972 client->authorized = 1; 00973 aji_send_header(client, client->jid->server); 00974 } 00975 break; 00976 case IKS_NODE_ERROR: 00977 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 00978 ASTOBJ_UNREF(client, aji_client_destroy); 00979 return IKS_HOOK; 00980 break; 00981 case IKS_NODE_STOP: 00982 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 00983 ASTOBJ_UNREF(client, aji_client_destroy); 00984 return IKS_HOOK; 00985 break; 00986 } 00987 } else if (client->state != AJI_CONNECTED && client->component) { 00988 switch (type) { 00989 case IKS_NODE_START: 00990 if (client->state == AJI_DISCONNECTED) { 00991 char secret[160], shasum[320], *handshake; 00992 00993 sprintf(secret, "%s%s", pak->id, client->password); 00994 ast_sha1_hash(shasum, secret); 00995 handshake = NULL; 00996 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 00997 aji_send_raw(client, handshake); 00998 ast_free(handshake); 00999 handshake = NULL; 01000 } 01001 client->state = AJI_CONNECTING; 01002 if(aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01003 client->state = AJI_CONNECTED; 01004 else 01005 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01006 break; 01007 } 01008 break; 01009 01010 case IKS_NODE_NORMAL: 01011 break; 01012 01013 case IKS_NODE_ERROR: 01014 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01015 ASTOBJ_UNREF(client, aji_client_destroy); 01016 return IKS_HOOK; 01017 01018 case IKS_NODE_STOP: 01019 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01020 ASTOBJ_UNREF(client, aji_client_destroy); 01021 return IKS_HOOK; 01022 } 01023 } 01024 01025 switch (pak->type) { 01026 case IKS_PAK_NONE: 01027 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01028 break; 01029 case IKS_PAK_MESSAGE: 01030 aji_handle_message(client, pak); 01031 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01032 break; 01033 case IKS_PAK_PRESENCE: 01034 aji_handle_presence(client, pak); 01035 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01036 break; 01037 case IKS_PAK_S10N: 01038 aji_handle_subscribe(client, pak); 01039 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01040 break; 01041 case IKS_PAK_IQ: 01042 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01043 aji_handle_iq(client, node); 01044 break; 01045 default: 01046 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01047 break; 01048 } 01049 01050 iks_filter_packet(client->f, pak); 01051 01052 if (node) 01053 iks_delete(node); 01054 01055 ASTOBJ_UNREF(client, aji_client_destroy); 01056 return IKS_OK; 01057 }
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 193 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().
00194 { 00195 struct aji_resource *tmp; 00196 00197 while ((tmp = obj->resources)) { 00198 obj->resources = obj->resources->next; 00199 ast_free(tmp->description); 00200 ast_free(tmp); 00201 } 00202 00203 ast_free(obj); 00204 }
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 2247 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().
02248 { 02249 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02250 int res = 0; 02251 02252 if (client) { 02253 if (client->state == AJI_DISCONNECTED) { 02254 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); 02255 client->state = AJI_CONNECTING; 02256 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 02257 iks_filter_remove_hook(client->f, aji_client_connect); 02258 if(!client->component) /*client*/ 02259 aji_get_roster(client); 02260 } 02261 } else 02262 ast_log(LOG_ERROR, "Out of memory.\n"); 02263 02264 ASTOBJ_UNREF(client, aji_client_destroy); 02265 return res; 02266 }
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 169 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_create_client(), aji_dinfo_handler(), aji_ditems_handler(), aji_log_hook(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), ast_aji_disconnect(), and unload_module().
00170 { 00171 struct aji_message *tmp; 00172 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy); 00173 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00174 iks_filter_delete(obj->f); 00175 iks_parser_delete(obj->p); 00176 iks_stack_delete(obj->stack); 00177 AST_LIST_LOCK(&obj->messages); 00178 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00179 if (tmp->from) 00180 ast_free(tmp->from); 00181 if (tmp->message) 00182 ast_free(tmp->message); 00183 } 00184 AST_LIST_HEAD_DESTROY(&obj->messages); 00185 ast_free(obj); 00186 }
static int aji_client_info_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handle add extra info.
data | void | |
pak | ikspak |
Definition at line 1273 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.
Referenced by aji_create_client().
01274 { 01275 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01276 struct aji_resource *resource = NULL; 01277 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01278 01279 resource = aji_find_resource(buddy, pak->from->resource); 01280 if (pak->subtype == IKS_TYPE_RESULT) { 01281 if (!resource) { 01282 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 01283 ASTOBJ_UNREF(client, aji_client_destroy); 01284 return IKS_FILTER_EAT; 01285 } 01286 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01287 resource->cap->jingle = 1; 01288 } else 01289 resource->cap->jingle = 0; 01290 } else if (pak->subtype == IKS_TYPE_GET) { 01291 iks *iq, *disco, *ident, *google, *query; 01292 iq = iks_new("iq"); 01293 query = iks_new("query"); 01294 ident = iks_new("identity"); 01295 disco = iks_new("feature"); 01296 google = iks_new("feature"); 01297 if (iq && ident && disco && google) { 01298 iks_insert_attrib(iq, "from", client->jid->full); 01299 iks_insert_attrib(iq, "to", pak->from->full); 01300 iks_insert_attrib(iq, "type", "result"); 01301 iks_insert_attrib(iq, "id", pak->id); 01302 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01303 iks_insert_attrib(ident, "category", "client"); 01304 iks_insert_attrib(ident, "type", "pc"); 01305 iks_insert_attrib(ident, "name", "asterisk"); 01306 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 01307 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 01308 iks_insert_node(iq, query); 01309 iks_insert_node(query, ident); 01310 iks_insert_node(query, google); 01311 iks_insert_node(query, disco); 01312 ast_aji_send(client, iq); 01313 } else 01314 ast_log(LOG_ERROR, "Out of Memory.\n"); 01315 01316 iks_delete(iq); 01317 iks_delete(query); 01318 iks_delete(ident); 01319 iks_delete(google); 01320 iks_delete(disco); 01321 } else if (pak->subtype == IKS_TYPE_ERROR) { 01322 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 01323 } 01324 ASTOBJ_UNREF(client, aji_client_destroy); 01325 return IKS_FILTER_EAT; 01326 }
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 |
1.
Definition at line 2848 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 2620 of file res_jabber.c.
References aji_act_hook(), AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_destroy(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_calloc, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, ast_free, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::f, aji_client::flags, aji_client::forcessl, globalflags, aji_client::jid, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, aji_client::name, aji_client::name_space, aji_client::p, aji_client::password, aji_client::port, aji_client::priority, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and var.
Referenced by aji_load_config().
02621 { 02622 char *resource; 02623 struct aji_client *client = NULL; 02624 int flag = 0; 02625 02626 client = ASTOBJ_CONTAINER_FIND(&clients,label); 02627 if (!client) { 02628 flag = 1; 02629 client = ast_calloc(1, sizeof(*client)); 02630 if (!client) { 02631 ast_log(LOG_ERROR, "Out of memory!\n"); 02632 return 0; 02633 } 02634 ASTOBJ_INIT(client); 02635 ASTOBJ_WRLOCK(client); 02636 ASTOBJ_CONTAINER_INIT(&client->buddies); 02637 } else { 02638 ASTOBJ_WRLOCK(client); 02639 ASTOBJ_UNMARK(client); 02640 } 02641 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 02642 ast_copy_string(client->name, label, sizeof(client->name)); 02643 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 02644 02645 /* Set default values for the client object */ 02646 client->debug = debug; 02647 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 02648 client->port = 5222; 02649 client->usetls = 1; 02650 client->usesasl = 1; 02651 client->forcessl = 0; 02652 client->keepalive = 1; 02653 client->timeout = 50; 02654 client->message_timeout = 100; 02655 AST_LIST_HEAD_INIT(&client->messages); 02656 client->component = 0; 02657 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 02658 client->priority = 0; 02659 client->status = IKS_SHOW_AVAILABLE; 02660 02661 if (flag) { 02662 client->authorized = 0; 02663 client->state = AJI_DISCONNECTED; 02664 } 02665 while (var) { 02666 if (!strcasecmp(var->name, "username")) 02667 ast_copy_string(client->user, var->value, sizeof(client->user)); 02668 else if (!strcasecmp(var->name, "serverhost")) 02669 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 02670 else if (!strcasecmp(var->name, "secret")) 02671 ast_copy_string(client->password, var->value, sizeof(client->password)); 02672 else if (!strcasecmp(var->name, "statusmessage")) 02673 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 02674 else if (!strcasecmp(var->name, "port")) 02675 client->port = atoi(var->value); 02676 else if (!strcasecmp(var->name, "timeout")) 02677 client->message_timeout = atoi(var->value); 02678 else if (!strcasecmp(var->name, "debug")) 02679 client->debug = (ast_false(var->value)) ? 0 : 1; 02680 else if (!strcasecmp(var->name, "type")) { 02681 if (!strcasecmp(var->value, "component")) 02682 client->component = 1; 02683 } else if (!strcasecmp(var->name, "usetls")) { 02684 client->usetls = (ast_false(var->value)) ? 0 : 1; 02685 } else if (!strcasecmp(var->name, "usesasl")) { 02686 client->usesasl = (ast_false(var->value)) ? 0 : 1; 02687 } else if (!strcasecmp(var->name, "forceoldssl")) 02688 client->forcessl = (ast_false(var->value)) ? 0 : 1; 02689 else if (!strcasecmp(var->name, "keepalive")) 02690 client->keepalive = (ast_false(var->value)) ? 0 : 1; 02691 else if (!strcasecmp(var->name, "autoprune")) 02692 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 02693 else if (!strcasecmp(var->name, "autoregister")) 02694 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 02695 else if (!strcasecmp(var->name, "buddy")) 02696 aji_create_buddy((char *)var->value, client); 02697 else if (!strcasecmp(var->name, "priority")) 02698 client->priority = atoi(var->value); 02699 else if (!strcasecmp(var->name, "status")) { 02700 if (!strcasecmp(var->value, "unavailable")) 02701 client->status = IKS_SHOW_UNAVAILABLE; 02702 else 02703 if (!strcasecmp(var->value, "available") 02704 || !strcasecmp(var->value, "online")) 02705 client->status = IKS_SHOW_AVAILABLE; 02706 else 02707 if (!strcasecmp(var->value, "chat") 02708 || !strcasecmp(var->value, "chatty")) 02709 client->status = IKS_SHOW_CHAT; 02710 else 02711 if (!strcasecmp(var->value, "away")) 02712 client->status = IKS_SHOW_AWAY; 02713 else 02714 if (!strcasecmp(var->value, "xa") 02715 || !strcasecmp(var->value, "xaway")) 02716 client->status = IKS_SHOW_XA; 02717 else 02718 if (!strcasecmp(var->value, "dnd")) 02719 client->status = IKS_SHOW_DND; 02720 else 02721 if (!strcasecmp(var->value, "invisible")) 02722 #ifdef IKS_SHOW_INVISIBLE 02723 client->status = IKS_SHOW_INVISIBLE; 02724 #else 02725 { 02726 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 02727 client->status = IKS_SHOW_DND; 02728 } 02729 #endif 02730 else 02731 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 02732 } 02733 /* no transport support in this version */ 02734 /* else if (!strcasecmp(var->name, "transport")) 02735 aji_create_transport(var->value, client); 02736 */ 02737 var = var->next; 02738 } 02739 if (!flag) { 02740 ASTOBJ_UNLOCK(client); 02741 ASTOBJ_UNREF(client, aji_client_destroy); 02742 return 1; 02743 } 02744 02745 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 02746 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 02747 if (!client->p) { 02748 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 02749 return 0; 02750 } 02751 client->stack = iks_stack_new(8192, 8192); 02752 if (!client->stack) { 02753 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 02754 return 0; 02755 } 02756 client->f = iks_filter_new(); 02757 if (!client->f) { 02758 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 02759 return 0; 02760 } 02761 if (!strchr(client->user, '/') && !client->component) { /*client */ 02762 resource = NULL; 02763 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02764 client->jid = iks_id_new(client->stack, resource); 02765 ast_free(resource); 02766 } 02767 } else 02768 client->jid = iks_id_new(client->stack, client->user); 02769 if (client->component) { 02770 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02771 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 02772 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); 02773 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); 02774 } else { 02775 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02776 } 02777 if (!strchr(client->user, '/') && !client->component) { /*client */ 02778 resource = NULL; 02779 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02780 client->jid = iks_id_new(client->stack, resource); 02781 ast_free(resource); 02782 } 02783 } else 02784 client->jid = iks_id_new(client->stack, client->user); 02785 iks_set_log_hook(client->p, aji_log_hook); 02786 ASTOBJ_UNLOCK(client); 02787 ASTOBJ_CONTAINER_LINK(&clients,client); 02788 return 1; 02789 }
static int aji_dinfo_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handler of the return info packet.
data | aji_client | |
pak | ikspak |
Definition at line 1333 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.
Referenced by aji_create_client().
01334 { 01335 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01336 char *node = NULL; 01337 struct aji_resource *resource = NULL; 01338 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01339 01340 resource = aji_find_resource(buddy, pak->from->resource); 01341 if (pak->subtype == IKS_TYPE_ERROR) { 01342 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 01343 return IKS_FILTER_EAT; 01344 } 01345 if (pak->subtype == IKS_TYPE_RESULT) { 01346 if (!resource) { 01347 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); 01348 ASTOBJ_UNREF(client, aji_client_destroy); 01349 return IKS_FILTER_EAT; 01350 } 01351 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01352 resource->cap->jingle = 1; 01353 } else 01354 resource->cap->jingle = 0; 01355 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 01356 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 01357 01358 iq = iks_new("iq"); 01359 query = iks_new("query"); 01360 identity = iks_new("identity"); 01361 disco = iks_new("feature"); 01362 reg = iks_new("feature"); 01363 commands = iks_new("feature"); 01364 gateway = iks_new("feature"); 01365 version = iks_new("feature"); 01366 vcard = iks_new("feature"); 01367 search = iks_new("feature"); 01368 01369 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 01370 iks_insert_attrib(iq, "from", client->user); 01371 iks_insert_attrib(iq, "to", pak->from->full); 01372 iks_insert_attrib(iq, "id", pak->id); 01373 iks_insert_attrib(iq, "type", "result"); 01374 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01375 iks_insert_attrib(identity, "category", "gateway"); 01376 iks_insert_attrib(identity, "type", "pstn"); 01377 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 01378 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 01379 iks_insert_attrib(reg, "var", "jabber:iq:register"); 01380 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 01381 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 01382 iks_insert_attrib(version, "var", "jabber:iq:version"); 01383 iks_insert_attrib(vcard, "var", "vcard-temp"); 01384 iks_insert_attrib(search, "var", "jabber:iq:search"); 01385 01386 iks_insert_node(iq, query); 01387 iks_insert_node(query, identity); 01388 iks_insert_node(query, disco); 01389 iks_insert_node(query, reg); 01390 iks_insert_node(query, commands); 01391 iks_insert_node(query, gateway); 01392 iks_insert_node(query, version); 01393 iks_insert_node(query, vcard); 01394 iks_insert_node(query, search); 01395 ast_aji_send(client, iq); 01396 } else { 01397 ast_log(LOG_ERROR, "Out of memory.\n"); 01398 } 01399 01400 iks_delete(iq); 01401 iks_delete(query); 01402 iks_delete(identity); 01403 iks_delete(disco); 01404 iks_delete(reg); 01405 iks_delete(commands); 01406 iks_delete(gateway); 01407 iks_delete(version); 01408 iks_delete(vcard); 01409 iks_delete(search); 01410 01411 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 01412 iks *iq, *query, *confirm; 01413 iq = iks_new("iq"); 01414 query = iks_new("query"); 01415 confirm = iks_new("item"); 01416 01417 if (iq && query && confirm && client) { 01418 iks_insert_attrib(iq, "from", client->user); 01419 iks_insert_attrib(iq, "to", pak->from->full); 01420 iks_insert_attrib(iq, "id", pak->id); 01421 iks_insert_attrib(iq, "type", "result"); 01422 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01423 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01424 iks_insert_attrib(confirm, "node", "confirmaccount"); 01425 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01426 iks_insert_attrib(confirm, "jid", client->user); 01427 iks_insert_node(iq, query); 01428 iks_insert_node(query, confirm); 01429 ast_aji_send(client, iq); 01430 } else { 01431 ast_log(LOG_ERROR, "Out of memory.\n"); 01432 } 01433 01434 iks_delete(iq); 01435 iks_delete(query); 01436 iks_delete(confirm); 01437 01438 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 01439 iks *iq, *query, *feature; 01440 01441 iq = iks_new("iq"); 01442 query = iks_new("query"); 01443 feature = iks_new("feature"); 01444 01445 if (iq && query && feature && client) { 01446 iks_insert_attrib(iq, "from", client->user); 01447 iks_insert_attrib(iq, "to", pak->from->full); 01448 iks_insert_attrib(iq, "id", pak->id); 01449 iks_insert_attrib(iq, "type", "result"); 01450 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01451 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01452 iks_insert_node(iq, query); 01453 iks_insert_node(query, feature); 01454 ast_aji_send(client, iq); 01455 } else { 01456 ast_log(LOG_ERROR, "Out of memory.\n"); 01457 } 01458 01459 iks_delete(iq); 01460 iks_delete(query); 01461 iks_delete(feature); 01462 } 01463 01464 ASTOBJ_UNREF(client, aji_client_destroy); 01465 return IKS_FILTER_EAT; 01466 }
static int aji_ditems_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handles stuff.
data | void | |
pak | ikspak |
Definition at line 1178 of file res_jabber.c.
References aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, and aji_client::user.
Referenced by aji_create_client().
01179 { 01180 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01181 char *node = NULL; 01182 01183 if (!(node = iks_find_attrib(pak->query, "node"))) { 01184 iks *iq = NULL, *query = NULL, *item = NULL; 01185 iq = iks_new("iq"); 01186 query = iks_new("query"); 01187 item = iks_new("item"); 01188 01189 if (iq && query && item) { 01190 iks_insert_attrib(iq, "from", client->user); 01191 iks_insert_attrib(iq, "to", pak->from->full); 01192 iks_insert_attrib(iq, "id", pak->id); 01193 iks_insert_attrib(iq, "type", "result"); 01194 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01195 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01196 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01197 iks_insert_attrib(item, "jid", client->user); 01198 01199 iks_insert_node(iq, query); 01200 iks_insert_node(query, item); 01201 ast_aji_send(client, iq); 01202 } else { 01203 ast_log(LOG_ERROR, "Out of memory.\n"); 01204 } 01205 01206 iks_delete(iq); 01207 iks_delete(query); 01208 iks_delete(item); 01209 01210 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01211 iks *iq, *query, *confirm; 01212 iq = iks_new("iq"); 01213 query = iks_new("query"); 01214 confirm = iks_new("item"); 01215 if (iq && query && confirm && client) { 01216 iks_insert_attrib(iq, "from", client->user); 01217 iks_insert_attrib(iq, "to", pak->from->full); 01218 iks_insert_attrib(iq, "id", pak->id); 01219 iks_insert_attrib(iq, "type", "result"); 01220 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01221 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01222 iks_insert_attrib(confirm, "node", "confirmaccount"); 01223 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01224 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01225 01226 iks_insert_node(iq, query); 01227 iks_insert_node(query, confirm); 01228 ast_aji_send(client, iq); 01229 } else { 01230 ast_log(LOG_ERROR, "Out of memory.\n"); 01231 } 01232 01233 iks_delete(iq); 01234 iks_delete(query); 01235 iks_delete(confirm); 01236 01237 } else if (!strcasecmp(node, "confirmaccount")) { 01238 iks *iq = NULL, *query = NULL, *feature = NULL; 01239 01240 iq = iks_new("iq"); 01241 query = iks_new("query"); 01242 feature = iks_new("feature"); 01243 01244 if (iq && query && feature && client) { 01245 iks_insert_attrib(iq, "from", client->user); 01246 iks_insert_attrib(iq, "to", pak->from->full); 01247 iks_insert_attrib(iq, "id", pak->id); 01248 iks_insert_attrib(iq, "type", "result"); 01249 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01250 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01251 iks_insert_node(iq, query); 01252 iks_insert_node(query, feature); 01253 ast_aji_send(client, iq); 01254 } else { 01255 ast_log(LOG_ERROR, "Out of memory.\n"); 01256 } 01257 01258 iks_delete(iq); 01259 iks_delete(query); 01260 iks_delete(feature); 01261 } 01262 01263 ASTOBJ_UNREF(client, aji_client_destroy); 01264 return IKS_FILTER_EAT; 01265 01266 }
static char * aji_do_debug_deprecated | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Turn on/off console debugging (deprecated, use aji_do_set_debug).
Definition at line 2402 of file res_jabber.c.
References ast_cli_args::argc, 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.
02403 { 02404 02405 switch (cmd) { 02406 case CLI_INIT: 02407 e->command = "jabber debug [off]"; 02408 e->usage = 02409 "Usage: jabber debug [off]\n" 02410 " Enables/disables dumping of Jabber packets for debugging purposes.\n"; 02411 return NULL; 02412 case CLI_GENERATE: 02413 return NULL; 02414 } 02415 02416 if (a->argc == 2) { 02417 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02418 ASTOBJ_RDLOCK(iterator); 02419 iterator->debug = 1; 02420 ASTOBJ_UNLOCK(iterator); 02421 }); 02422 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02423 return CLI_SUCCESS; 02424 } else if (a->argc == 3) { 02425 if (!strncasecmp(a->argv[2], "off", 3)) { 02426 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02427 ASTOBJ_RDLOCK(iterator); 02428 iterator->debug = 0; 02429 ASTOBJ_UNLOCK(iterator); 02430 }); 02431 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02432 return CLI_SUCCESS; 02433 } 02434 } 02435 return CLI_SHOWUSAGE; /* defaults to invalid */ 02436 }
static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Reload jabber module.
Definition at line 2442 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.
02443 { 02444 switch (cmd) { 02445 case CLI_INIT: 02446 e->command = "jabber reload"; 02447 e->usage = 02448 "Usage: jabber reload\n" 02449 " Reloads the Jabber module.\n"; 02450 return NULL; 02451 case CLI_GENERATE: 02452 return NULL; 02453 } 02454 02455 aji_reload(1); 02456 ast_cli(a->fd, "Jabber Reloaded.\n"); 02457 return CLI_SUCCESS; 02458 }
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 2362 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.
02363 { 02364 switch (cmd) { 02365 case CLI_INIT: 02366 e->command = "jabber set debug {on|off}"; 02367 e->usage = 02368 "Usage: jabber set debug {on|off}\n" 02369 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 02370 return NULL; 02371 case CLI_GENERATE: 02372 return NULL; 02373 } 02374 02375 if (a->argc != e->args) 02376 return CLI_SHOWUSAGE; 02377 02378 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 02379 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02380 ASTOBJ_RDLOCK(iterator); 02381 iterator->debug = 1; 02382 ASTOBJ_UNLOCK(iterator); 02383 }); 02384 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02385 return CLI_SUCCESS; 02386 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 02387 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02388 ASTOBJ_RDLOCK(iterator); 02389 iterator->debug = 0; 02390 ASTOBJ_UNLOCK(iterator); 02391 }); 02392 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02393 return CLI_SUCCESS; 02394 } 02395 return CLI_SHOWUSAGE; /* defaults to invalid */ 02396 }
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 2120 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().
02121 { 02122 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02123 int flag = 0; 02124 iks *x = NULL; 02125 struct aji_buddy *buddy; 02126 02127 client->state = AJI_CONNECTED; 02128 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02129 ASTOBJ_RDLOCK(iterator); 02130 x = iks_child(pak->query); 02131 flag = 0; 02132 while (x) { 02133 if (!iks_strcmp(iks_name(x), "item")) { 02134 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02135 flag = 1; 02136 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02137 } 02138 } 02139 x = iks_next(x); 02140 } 02141 if (!flag) 02142 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02143 iks_delete(x); 02144 02145 ASTOBJ_UNLOCK(iterator); 02146 }); 02147 02148 x = iks_child(pak->query); 02149 while (x) { 02150 flag = 0; 02151 if (iks_strcmp(iks_name(x), "item") == 0) { 02152 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02153 ASTOBJ_RDLOCK(iterator); 02154 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02155 flag = 1; 02156 ASTOBJ_UNLOCK(iterator); 02157 }); 02158 02159 if (flag) { 02160 /* found buddy, don't create a new one */ 02161 x = iks_next(x); 02162 continue; 02163 } 02164 02165 buddy = ast_calloc(1, sizeof(*buddy)); 02166 if (!buddy) { 02167 ast_log(LOG_WARNING, "Out of memory\n"); 02168 return 0; 02169 } 02170 ASTOBJ_INIT(buddy); 02171 ASTOBJ_WRLOCK(buddy); 02172 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02173 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02174 if(ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02175 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 02176 ASTOBJ_MARK(buddy); 02177 } else if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 02178 /* subscribe to buddy's presence only 02179 if we really need to */ 02180 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 02181 } 02182 ASTOBJ_UNLOCK(buddy); 02183 if (buddy) { 02184 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 02185 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02186 } 02187 } 02188 x = iks_next(x); 02189 } 02190 02191 iks_delete(x); 02192 aji_pruneregister(client); 02193 02194 ASTOBJ_UNREF(client, aji_client_destroy); 02195 return IKS_FILTER_EAT; 02196 }
static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
char * | name | |||
) | [static] |
Find the aji_resource we want.
buddy | aji_buddy A buddy | |
name |
Definition at line 282 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().
00283 { 00284 struct aji_resource *res = NULL; 00285 if (!buddy || !name) 00286 return res; 00287 res = buddy->resources; 00288 while (res) { 00289 if (!strcasecmp(res->resource, name)) { 00290 break; 00291 } 00292 res = res->next; 00293 } 00294 return res; 00295 }
static struct aji_version* aji_find_version | ( | char * | node, | |
char * | version, | |||
ikspak * | pak | |||
) | [static] |
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 215 of file res_jabber.c.
References ast_copy_string(), ast_free, ast_log(), ast_malloc, capabilities, LOG_ERROR, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::version, and aji_capabilities::versions.
Referenced by aji_handle_presence().
00216 { 00217 struct aji_capabilities *list = NULL; 00218 struct aji_version *res = NULL; 00219 00220 list = capabilities; 00221 00222 if(!node) 00223 node = pak->from->full; 00224 if(!version) 00225 version = "none supplied."; 00226 while(list) { 00227 if(!strcasecmp(list->node, node)) { 00228 res = list->versions; 00229 while(res) { 00230 if(!strcasecmp(res->version, version)) 00231 return res; 00232 res = res->next; 00233 } 00234 /* Specified version not found. Let's add it to 00235 this node in our capabilities list */ 00236 if(!res) { 00237 res = ast_malloc(sizeof(*res)); 00238 if(!res) { 00239 ast_log(LOG_ERROR, "Out of memory!\n"); 00240 return NULL; 00241 } 00242 res->jingle = 0; 00243 res->parent = list; 00244 ast_copy_string(res->version, version, sizeof(res->version)); 00245 res->next = list->versions; 00246 list->versions = res; 00247 return res; 00248 } 00249 } 00250 list = list->next; 00251 } 00252 /* Specified node not found. Let's add it our capabilities list */ 00253 if(!list) { 00254 list = ast_malloc(sizeof(*list)); 00255 if(!list) { 00256 ast_log(LOG_ERROR, "Out of memory!\n"); 00257 return NULL; 00258 } 00259 res = ast_malloc(sizeof(*res)); 00260 if(!res) { 00261 ast_log(LOG_ERROR, "Out of memory!\n"); 00262 ast_free(list); 00263 return NULL; 00264 } 00265 ast_copy_string(list->node, node, sizeof(list->node)); 00266 ast_copy_string(res->version, version, sizeof(res->version)); 00267 res->jingle = 0; 00268 res->parent = list; 00269 res->next = NULL; 00270 list->versions = res; 00271 list->next = capabilities; 00272 capabilities = list; 00273 } 00274 return res; 00275 }
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 2225 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().
02226 { 02227 iks *roster = NULL; 02228 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 02229 02230 if(roster) { 02231 iks_insert_attrib(roster, "id", "roster"); 02232 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 02233 ast_aji_send(client, roster); 02234 } 02235 02236 iks_delete(roster); 02237 02238 return 1; 02239 }
static void aji_handle_iq | ( | struct aji_client * | client, | |
iks * | node | |||
) | [static] |
Handles.
<iq>
client | the configured XMPP client we use to connect to a XMPP server | |
node | iks |
Definition at line 1474 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 1484 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::list, aji_message::message, aji_client::message_timeout, and aji_client::messages.
Referenced by aji_act_hook().
01485 { 01486 struct aji_message *insert, *tmp; 01487 int flag = 0; 01488 01489 if (!(insert = ast_calloc(1, sizeof(*insert)))) 01490 return; 01491 time(&insert->arrived); 01492 if (iks_find_cdata(pak->x, "body")) 01493 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 01494 if (pak->id) 01495 ast_copy_string(insert->id, pak->id, sizeof(insert->message)); 01496 if (pak->from) 01497 insert->from = ast_strdup(pak->from->full); 01498 AST_LIST_LOCK(&client->messages); 01499 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 01500 if (flag) { 01501 AST_LIST_REMOVE_CURRENT(list); 01502 if (tmp->from) 01503 ast_free(tmp->from); 01504 if (tmp->message) 01505 ast_free(tmp->message); 01506 } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) { 01507 flag = 1; 01508 AST_LIST_REMOVE_CURRENT(list); 01509 if (tmp->from) 01510 ast_free(tmp->from); 01511 if (tmp->message) 01512 ast_free(tmp->message); 01513 } 01514 } 01515 AST_LIST_TRAVERSE_SAFE_END; 01516 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 01517 AST_LIST_UNLOCK(&client->messages); 01518 }
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 1524 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, type, and ver.
Referenced by aji_act_hook().
01525 { 01526 int status, priority; 01527 struct aji_buddy *buddy; 01528 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 01529 char *ver, *node, *descrip, *type; 01530 01531 if(client->state != AJI_CONNECTED) 01532 aji_create_buddy(pak->from->partial, client); 01533 01534 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01535 if (!buddy && pak->from->partial) { 01536 /* allow our jid to be used to log in with another resource */ 01537 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 01538 aji_create_buddy(pak->from->partial, client); 01539 else 01540 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 01541 return; 01542 } 01543 type = iks_find_attrib(pak->x, "type"); 01544 if(client->component && type &&!strcasecmp("probe", type)) { 01545 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01546 ast_verbose("what i was looking for \n"); 01547 } 01548 ASTOBJ_WRLOCK(buddy); 01549 status = (pak->show) ? pak->show : 6; 01550 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 01551 tmp = buddy->resources; 01552 descrip = ast_strdup(iks_find_cdata(pak->x,"status")); 01553 01554 while (tmp && pak->from->resource) { 01555 if (!strcasecmp(tmp->resource, pak->from->resource)) { 01556 tmp->status = status; 01557 if (tmp->description) ast_free(tmp->description); 01558 tmp->description = descrip; 01559 found = tmp; 01560 if (status == 6) { /* Sign off Destroy resource */ 01561 if (last && found->next) { 01562 last->next = found->next; 01563 } else if (!last) { 01564 if (found->next) 01565 buddy->resources = found->next; 01566 else 01567 buddy->resources = NULL; 01568 } else if (!found->next) { 01569 if (last) 01570 last->next = NULL; 01571 else 01572 buddy->resources = NULL; 01573 } 01574 ast_free(found); 01575 found = NULL; 01576 break; 01577 } 01578 /* resource list is sorted by descending priority */ 01579 if (tmp->priority != priority) { 01580 found->priority = priority; 01581 if (!last && !found->next) 01582 /* resource was found to be unique, 01583 leave loop */ 01584 break; 01585 /* search for resource in our list 01586 and take it out for the moment */ 01587 if (last) 01588 last->next = found->next; 01589 else 01590 buddy->resources = found->next; 01591 01592 last = NULL; 01593 tmp = buddy->resources; 01594 if (!buddy->resources) 01595 buddy->resources = found; 01596 /* priority processing */ 01597 while (tmp) { 01598 /* insert resource back according to 01599 its priority value */ 01600 if (found->priority > tmp->priority) { 01601 if (last) 01602 /* insert within list */ 01603 last->next = found; 01604 found->next = tmp; 01605 if (!last) 01606 /* insert on top */ 01607 buddy->resources = found; 01608 break; 01609 } 01610 if (!tmp->next) { 01611 /* insert at the end of the list */ 01612 tmp->next = found; 01613 found->next = NULL; 01614 break; 01615 } 01616 last = tmp; 01617 tmp = tmp->next; 01618 } 01619 } 01620 break; 01621 } 01622 last = tmp; 01623 tmp = tmp->next; 01624 } 01625 01626 /* resource not found in our list, create it */ 01627 if (!found && status != 6 && pak->from->resource) { 01628 found = ast_calloc(1, sizeof(*found)); 01629 01630 if (!found) { 01631 ast_log(LOG_ERROR, "Out of memory!\n"); 01632 return; 01633 } 01634 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 01635 found->status = status; 01636 found->description = descrip; 01637 found->priority = priority; 01638 found->next = NULL; 01639 last = NULL; 01640 tmp = buddy->resources; 01641 while (tmp) { 01642 if (found->priority > tmp->priority) { 01643 if (last) 01644 last->next = found; 01645 found->next = tmp; 01646 if (!last) 01647 buddy->resources = found; 01648 break; 01649 } 01650 if (!tmp->next) { 01651 tmp->next = found; 01652 break; 01653 } 01654 last = tmp; 01655 tmp = tmp->next; 01656 } 01657 if (!tmp) 01658 buddy->resources = found; 01659 } 01660 01661 ASTOBJ_UNLOCK(buddy); 01662 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 01663 01664 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 01665 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 01666 01667 /* handle gmail client's special caps:c tag */ 01668 if (!node && !ver) { 01669 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 01670 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 01671 } 01672 01673 /* retrieve capabilites of the new resource */ 01674 if(status !=6 && found && !found->cap) { 01675 found->cap = aji_find_version(node, ver, pak); 01676 if(gtalk_yuck(pak->x)) /* gtalk should do discover */ 01677 found->cap->jingle = 1; 01678 if(found->cap->jingle && option_debug > 4) { 01679 ast_debug(1,"Special case for google till they support discover.\n"); 01680 } 01681 else { 01682 iks *iq, *query; 01683 iq = iks_new("iq"); 01684 query = iks_new("query"); 01685 if(query && iq) { 01686 iks_insert_attrib(iq, "type", "get"); 01687 iks_insert_attrib(iq, "to", pak->from->full); 01688 iks_insert_attrib(iq,"from", client->jid->full); 01689 iks_insert_attrib(iq, "id", client->mid); 01690 ast_aji_increment_mid(client->mid); 01691 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01692 iks_insert_node(iq, query); 01693 ast_aji_send(client, iq); 01694 01695 } else 01696 ast_log(LOG_ERROR, "Out of memory.\n"); 01697 01698 iks_delete(query); 01699 iks_delete(iq); 01700 } 01701 } 01702 switch (pak->subtype) { 01703 case IKS_TYPE_AVAILABLE: 01704 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 01705 break; 01706 case IKS_TYPE_UNAVAILABLE: 01707 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 01708 break; 01709 default: 01710 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 01711 } 01712 switch (pak->show) { 01713 case IKS_SHOW_UNAVAILABLE: 01714 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01715 break; 01716 case IKS_SHOW_AVAILABLE: 01717 ast_debug(3, "JABBER: type is available\n"); 01718 break; 01719 case IKS_SHOW_CHAT: 01720 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01721 break; 01722 case IKS_SHOW_AWAY: 01723 ast_debug(3, "JABBER: type is away\n"); 01724 break; 01725 case IKS_SHOW_XA: 01726 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01727 break; 01728 case IKS_SHOW_DND: 01729 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01730 break; 01731 default: 01732 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 01733 } 01734 }
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 1742 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().
01743 { 01744 iks *presence = NULL, *status = NULL; 01745 struct aji_buddy* buddy = NULL; 01746 01747 switch (pak->subtype) { 01748 case IKS_TYPE_SUBSCRIBE: 01749 presence = iks_new("presence"); 01750 status = iks_new("status"); 01751 if (presence && status) { 01752 iks_insert_attrib(presence, "type", "subscribed"); 01753 iks_insert_attrib(presence, "to", pak->from->full); 01754 iks_insert_attrib(presence, "from", client->jid->full); 01755 if (pak->id) 01756 iks_insert_attrib(presence, "id", pak->id); 01757 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 01758 iks_insert_node(presence, status); 01759 ast_aji_send(client, presence); 01760 } else 01761 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 01762 01763 iks_delete(presence); 01764 iks_delete(status); 01765 01766 if (client->component) 01767 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01768 case IKS_TYPE_SUBSCRIBED: 01769 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01770 if (!buddy && pak->from->partial) { 01771 aji_create_buddy(pak->from->partial, client); 01772 } 01773 default: 01774 if (option_verbose > 4) { 01775 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 01776 } 01777 } 01778 }
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 2273 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, and aji_client::user.
Referenced by aji_reconnect().
02274 { 02275 int connected = IKS_NET_NOCONN; 02276 02277 #ifdef HAVE_OPENSSL 02278 /* reset stream flags */ 02279 client->stream_flags = 0; 02280 #endif 02281 /* If it's a component, connect to user, otherwise, connect to server */ 02282 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 02283 02284 if (connected == IKS_NET_NOCONN) { 02285 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 02286 return IKS_HOOK; 02287 } else if (connected == IKS_NET_NODNS) { 02288 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server)); 02289 return IKS_HOOK; 02290 } 02291 02292 return IKS_OK; 02293 }
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 589 of file res_jabber.c.
References aji_is_secure(), ast_select(), len(), and aji_client::p.
Referenced by aji_recv().
00590 { 00591 int sock; 00592 fd_set fds; 00593 struct timeval tv, *tvptr = NULL; 00594 int len, res; 00595 00596 #ifdef HAVE_OPENSSL 00597 if (aji_is_secure(client)) { 00598 sock = SSL_get_fd(client->ssl_session); 00599 if (sock < 0) 00600 return -1; 00601 } else 00602 #endif /* HAVE_OPENSSL */ 00603 sock = iks_fd(client->p); 00604 00605 memset(&tv, 0, sizeof(struct timeval)); 00606 FD_ZERO(&fds); 00607 FD_SET(sock, &fds); 00608 tv.tv_sec = timeout; 00609 00610 /* NULL value for tvptr makes ast_select wait indefinitely */ 00611 tvptr = (timeout != -1) ? &tv : NULL; 00612 00613 /* ast_select emulates linux behaviour in terms of timeout handling */ 00614 res = ast_select(sock + 1, &fds, NULL, NULL, tvptr); 00615 if (res > 0) { 00616 #ifdef HAVE_OPENSSL 00617 if (aji_is_secure(client)) { 00618 len = SSL_read(client->ssl_session, buffer, buf_len); 00619 } else 00620 #endif /* HAVE_OPENSSL */ 00621 len = recv(sock, buffer, buf_len, 0); 00622 00623 if (len > 0) { 00624 return len; 00625 } else if (len <= 0) { 00626 return -1; 00627 } 00628 } 00629 return res; 00630 }
static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Tests whether the connection is secured or not.
Definition at line 503 of file res_jabber.c.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
00504 { 00505 #ifdef HAVE_OPENSSL 00506 return client->stream_flags & SECURE; 00507 #else 00508 return 0; 00509 #endif 00510 }
static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 2875 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_flags, CONFIG_STATUS_FILEUNCHANGED, debug, globalflags, JABBER_CONFIG, LOG_WARNING, and var.
Referenced by aji_reload().
02876 { 02877 char *cat = NULL; 02878 int debug = 1; 02879 struct ast_config *cfg = NULL; 02880 struct ast_variable *var = NULL; 02881 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02882 02883 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 02884 return -1; 02885 02886 /* Reset flags to default value */ 02887 ast_set_flag(&globalflags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02888 02889 if (!cfg) { 02890 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 02891 return 0; 02892 } 02893 02894 cat = ast_category_browse(cfg, NULL); 02895 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 02896 if (!strcasecmp(var->name, "debug")) 02897 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 02898 else if (!strcasecmp(var->name, "autoprune")) 02899 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 02900 else if (!strcasecmp(var->name, "autoregister")) 02901 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 02902 } 02903 02904 while (cat) { 02905 if (strcasecmp(cat, "general")) { 02906 var = ast_variable_browse(cfg, cat); 02907 aji_create_client(cat, var, debug); 02908 } 02909 cat = ast_category_browse(cfg, cat); 02910 } 02911 ast_config_destroy(cfg); /* or leak memory */ 02912 return 1; 02913 }
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 783 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_create_client(), aji_recv(), and aji_send_raw().
00784 { 00785 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00786 00787 if (!ast_strlen_zero(xmpp)) 00788 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 00789 00790 if (client->debug) { 00791 if (is_incoming) 00792 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 00793 else { 00794 if( strlen(xmpp) == 1) { 00795 if(option_debug > 2 && xmpp[0] == ' ') { 00796 ast_verbose("\nJABBER: Keep alive packet\n"); 00797 } 00798 } else 00799 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 00800 } 00801 00802 } 00803 ASTOBJ_UNREF(client, aji_client_destroy); 00804 }
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 2066 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.
02067 { 02068 int res = 0; 02069 iks *removeiq = iks_new("iq"); 02070 iks *removequery = iks_new("query"); 02071 iks *removeitem = iks_new("item"); 02072 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02073 if (!client || !removeiq || !removequery || !removeitem || !send) { 02074 ast_log(LOG_ERROR, "Out of memory.\n"); 02075 goto safeout; 02076 } 02077 02078 iks_insert_node(removeiq, removequery); 02079 iks_insert_node(removequery, removeitem); 02080 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02081 ASTOBJ_RDLOCK(iterator); 02082 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02083 * be called at the same time */ 02084 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { 02085 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02086 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02087 " so I am no longer subscribing to your presence.\n")); 02088 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02089 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02090 " your access to my presence.\n")); 02091 iks_insert_attrib(removeiq, "from", client->jid->full); 02092 iks_insert_attrib(removeiq, "type", "set"); 02093 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02094 iks_insert_attrib(removeitem, "jid", iterator->name); 02095 iks_insert_attrib(removeitem, "subscription", "remove"); 02096 res = ast_aji_send(client, removeiq); 02097 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02098 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02099 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02100 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02101 } 02102 ASTOBJ_UNLOCK(iterator); 02103 }); 02104 02105 safeout: 02106 iks_delete(removeiq); 02107 iks_delete(removequery); 02108 iks_delete(removeitem); 02109 iks_delete(send); 02110 02111 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); 02112 }
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 2203 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().
02204 { 02205 int res = 0; 02206 02207 if (client->state) 02208 client->state = AJI_DISCONNECTED; 02209 client->timeout=50; 02210 if (client->p) 02211 iks_parser_reset(client->p); 02212 if (client->authorized) 02213 client->authorized = 0; 02214 02215 res = aji_initialize(client); 02216 02217 return res; 02218 }
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 641 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().
00642 { 00643 int len, ret; 00644 char buf[NET_IO_BUF_SIZE - 1]; 00645 char newbuf[NET_IO_BUF_SIZE - 1]; 00646 int pos = 0; 00647 int newbufpos = 0; 00648 unsigned char c; 00649 00650 memset(buf, 0, sizeof(buf)); 00651 memset(newbuf, 0, sizeof(newbuf)); 00652 00653 while (1) { 00654 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 00655 if (len < 0) return IKS_NET_RWERR; 00656 if (len == 0) return IKS_NET_EXPIRED; 00657 buf[len] = '\0'; 00658 00659 /* our iksemel parser won't work as expected if we feed 00660 it with XML packets that contain multiple whitespace 00661 characters between tags */ 00662 while (pos < len) { 00663 c = buf[pos]; 00664 /* if we stumble on the ending tag character, 00665 we skip any whitespace that follows it*/ 00666 if (c == '>') { 00667 while (isspace(buf[pos+1])) { 00668 pos++; 00669 } 00670 } 00671 newbuf[newbufpos] = c; 00672 newbufpos ++; 00673 pos++; 00674 } 00675 pos = 0; 00676 newbufpos = 0; 00677 00678 /* Log the message here, because iksemel's logHook is 00679 unaccessible */ 00680 aji_log_hook(client, buf, len, 1); 00681 00682 /* let iksemel deal with the string length, 00683 and reset our buffer */ 00684 ret = iks_parse(client->p, newbuf, 0, 0); 00685 memset(newbuf, 0, sizeof(newbuf)); 00686 00687 switch (ret) { 00688 case IKS_NOMEM: 00689 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 00690 break; 00691 case IKS_BADXML: 00692 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 00693 break; 00694 case IKS_HOOK: 00695 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 00696 break; 00697 } 00698 if (ret != IKS_OK) { 00699 return ret; 00700 } 00701 ast_debug(3, "XML parsing successful\n"); 00702 } 00703 return IKS_OK; 00704 }
static void * aji_recv_loop | ( | void * | data | ) | [static] |
receive message loop.
data | void |
Definition at line 1905 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().
01906 { 01907 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01908 int res = IKS_HOOK; 01909 01910 while(res != IKS_OK) { 01911 ast_debug(3, "JABBER: Connecting.\n"); 01912 res = aji_reconnect(client); 01913 sleep(4); 01914 } 01915 01916 do { 01917 if (res == IKS_NET_RWERR || client->timeout == 0) { 01918 while(res != IKS_OK) { 01919 ast_debug(3, "JABBER: reconnecting.\n"); 01920 res = aji_reconnect(client); 01921 sleep(4); 01922 } 01923 } 01924 01925 res = aji_recv(client, 1); 01926 01927 if (client->state == AJI_DISCONNECTING) { 01928 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 01929 pthread_exit(NULL); 01930 } 01931 01932 /* Decrease timeout if no data received */ 01933 if (res == IKS_NET_EXPIRED) 01934 client->timeout--; 01935 01936 if (res == IKS_HOOK) 01937 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 01938 else if (res == IKS_NET_TLSFAIL) 01939 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 01940 else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 01941 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 01942 if(res == IKS_OK) 01943 client->timeout = 50; 01944 else 01945 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 01946 } else if (res == IKS_NET_RWERR) 01947 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 01948 } while (client); 01949 ASTOBJ_UNREF(client, aji_client_destroy); 01950 return 0; 01951 }
static int aji_register_approve_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Unknown.
data | void | |
pak | ikspak |
Definition at line 1064 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.
Referenced by aji_create_client().
01065 { 01066 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01067 iks *iq = NULL, *presence = NULL, *x = NULL; 01068 01069 iq = iks_new("iq"); 01070 presence = iks_new("presence"); 01071 x = iks_new("x"); 01072 if (client && iq && presence && x) { 01073 if (!iks_find(pak->query, "remove")) { 01074 iks_insert_attrib(iq, "from", client->jid->full); 01075 iks_insert_attrib(iq, "to", pak->from->full); 01076 iks_insert_attrib(iq, "id", pak->id); 01077 iks_insert_attrib(iq, "type", "result"); 01078 ast_aji_send(client, iq); 01079 01080 iks_insert_attrib(presence, "from", client->jid->full); 01081 iks_insert_attrib(presence, "to", pak->from->partial); 01082 iks_insert_attrib(presence, "id", client->mid); 01083 ast_aji_increment_mid(client->mid); 01084 iks_insert_attrib(presence, "type", "subscribe"); 01085 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01086 iks_insert_node(presence, x); 01087 ast_aji_send(client, presence); 01088 } 01089 } else { 01090 ast_log(LOG_ERROR, "Out of memory.\n"); 01091 } 01092 01093 01094 iks_delete(iq); 01095 iks_delete(presence); 01096 iks_delete(x); 01097 01098 ASTOBJ_UNREF(client, aji_client_destroy); 01099 return IKS_FILTER_EAT; 01100 }
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 1107 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.
Referenced by aji_create_client().
01108 { 01109 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01110 struct aji_buddy *buddy = NULL; 01111 char *node = NULL; 01112 iks *iq = NULL, *query = NULL; 01113 01114 client = (struct aji_client *) data; 01115 01116 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01117 if (!buddy) { 01118 iks *error = NULL, *notacceptable = NULL; 01119 01120 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01121 iq = iks_new("iq"); 01122 query = iks_new("query"); 01123 error = iks_new("error"); 01124 notacceptable = iks_new("not-acceptable"); 01125 if(iq && query && error && notacceptable) { 01126 iks_insert_attrib(iq, "type", "error"); 01127 iks_insert_attrib(iq, "from", client->user); 01128 iks_insert_attrib(iq, "to", pak->from->full); 01129 iks_insert_attrib(iq, "id", pak->id); 01130 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01131 iks_insert_attrib(error, "code" , "406"); 01132 iks_insert_attrib(error, "type", "modify"); 01133 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01134 iks_insert_node(iq, query); 01135 iks_insert_node(iq, error); 01136 iks_insert_node(error, notacceptable); 01137 ast_aji_send(client, iq); 01138 } else { 01139 ast_log(LOG_ERROR, "Out of memory.\n"); 01140 } 01141 01142 iks_delete(error); 01143 iks_delete(notacceptable); 01144 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01145 iks *instructions = NULL; 01146 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01147 iq = iks_new("iq"); 01148 query = iks_new("query"); 01149 instructions = iks_new("instructions"); 01150 if (iq && query && instructions && client) { 01151 iks_insert_attrib(iq, "from", client->user); 01152 iks_insert_attrib(iq, "to", pak->from->full); 01153 iks_insert_attrib(iq, "id", pak->id); 01154 iks_insert_attrib(iq, "type", "result"); 01155 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01156 iks_insert_cdata(instructions, explain, 0); 01157 iks_insert_node(iq, query); 01158 iks_insert_node(query, instructions); 01159 ast_aji_send(client, iq); 01160 } else { 01161 ast_log(LOG_ERROR, "Out of memory.\n"); 01162 } 01163 01164 iks_delete(instructions); 01165 } 01166 iks_delete(iq); 01167 iks_delete(query); 01168 ASTOBJ_UNREF(client, aji_client_destroy); 01169 return IKS_FILTER_EAT; 01170 }
static int aji_reload | ( | int | reload | ) | [static] |
Reload the jabber module.
Definition at line 3002 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().
03003 { 03004 int res; 03005 03006 ASTOBJ_CONTAINER_MARKALL(&clients); 03007 if (!(res = aji_load_config(reload))) { 03008 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 03009 return 0; 03010 } else if (res == -1) 03011 return 1; 03012 03013 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); 03014 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03015 ASTOBJ_RDLOCK(iterator); 03016 if(iterator->state == AJI_DISCONNECTED) { 03017 if (!iterator->thread) 03018 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 03019 } else if (iterator->state == AJI_CONNECTING) 03020 aji_get_roster(iterator); 03021 ASTOBJ_UNLOCK(iterator); 03022 }); 03023 03024 return 1; 03025 }
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 468 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_strdupa, ast_strlen_zero(), LOG_ERROR, LOG_WARNING, and s.
Referenced by load_module().
00469 { 00470 struct aji_client *client = NULL; 00471 char *s; 00472 AST_DECLARE_APP_ARGS(args, 00473 AST_APP_ARG(sender); 00474 AST_APP_ARG(recipient); 00475 AST_APP_ARG(message); 00476 ); 00477 00478 if (!data) { 00479 ast_log(LOG_ERROR, "Usage: JabberSend(<sender>,<recipient>,<message>)\n"); 00480 return 0; 00481 } 00482 s = ast_strdupa(data); 00483 00484 AST_STANDARD_APP_ARGS(args, s); 00485 if (args.argc < 3) { 00486 ast_log(LOG_ERROR, "JabberSend requires 3 arguments: '%s'\n", (char *) data); 00487 return -1; 00488 } 00489 00490 if (!(client = ast_aji_get_client(args.sender))) { 00491 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00492 return -1; 00493 } 00494 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) 00495 ast_aji_send_chat(client, args.recipient, args.message); 00496 return 0; 00497 }
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 712 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().
00713 { 00714 char *msg; 00715 int len, err; 00716 00717 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 00718 msg = iks_malloc(len); 00719 if (!msg) 00720 return IKS_NOMEM; 00721 sprintf(msg, "<?xml version='1.0'?>" 00722 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 00723 "%s' to='%s' version='1.0'>", client->name_space, to); 00724 err = aji_send_raw(client, msg); 00725 iks_free(msg); 00726 if (err != IKS_OK) 00727 return err; 00728 00729 return IKS_OK; 00730 }
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 751 of file res_jabber.c.
References aji_is_secure(), aji_log_hook(), len(), and aji_client::p.
Referenced by aji_act_hook(), aji_recv_loop(), aji_send_header(), and ast_aji_send().
00752 { 00753 int ret; 00754 #ifdef HAVE_OPENSSL 00755 int len = strlen(xmlstr); 00756 00757 if (aji_is_secure(client)) { 00758 ret = SSL_write(client->ssl_session, xmlstr, len); 00759 if (ret) { 00760 /* Log the message here, because iksemel's logHook is 00761 unaccessible */ 00762 aji_log_hook(client, xmlstr, len, 0); 00763 return IKS_OK; 00764 } 00765 } 00766 #endif 00767 /* If needed, data will be sent unencrypted, and logHook will 00768 be called inside iks_send_raw */ 00769 ret = iks_send_raw(client->p, xmlstr); 00770 if (ret != IKS_OK) 00771 return ret; 00772 00773 return IKS_OK; 00774 }
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 2328 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().
02329 { 02330 int res = 0; 02331 iks *presence = iks_make_pres(level, desc); 02332 iks *cnode = iks_new("c"); 02333 iks *priority = iks_new("priority"); 02334 char priorityS[10]; 02335 02336 if (presence && cnode && client && priority) { 02337 if(to) 02338 iks_insert_attrib(presence, "to", to); 02339 if(from) 02340 iks_insert_attrib(presence, "from", from); 02341 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 02342 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 02343 iks_insert_node(presence, priority); 02344 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 02345 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 02346 iks_insert_attrib(cnode, "ext", "voice-v1"); 02347 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 02348 iks_insert_node(presence, cnode); 02349 res = ast_aji_send(client, presence); 02350 } else 02351 ast_log(LOG_ERROR, "Out of memory.\n"); 02352 02353 iks_delete(cnode); 02354 iks_delete(presence); 02355 iks_delete(priority); 02356 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show buddy lists.
Definition at line 2509 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.
02510 { 02511 struct aji_resource *resource; 02512 struct aji_client *client; 02513 02514 switch (cmd) { 02515 case CLI_INIT: 02516 e->command = "jabber show buddies"; 02517 e->usage = 02518 "Usage: jabber show buddies\n" 02519 " Shows buddy lists of our clients\n"; 02520 return NULL; 02521 case CLI_GENERATE: 02522 return NULL; 02523 } 02524 02525 ast_cli(a->fd, "Jabber buddy lists\n"); 02526 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02527 ast_cli(a->fd,"Client: %s\n", iterator->user); 02528 client = iterator; 02529 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02530 ASTOBJ_RDLOCK(iterator); 02531 ast_cli(a->fd,"\tBuddy:\t%s\n", iterator->name); 02532 if (!iterator->resources) 02533 ast_cli(a->fd,"\t\tResource: None\n"); 02534 for (resource = iterator->resources; resource; resource = resource->next) { 02535 ast_cli(a->fd,"\t\tResource: %s\n", resource->resource); 02536 if(resource->cap) { 02537 ast_cli(a->fd,"\t\t\tnode: %s\n", resource->cap->parent->node); 02538 ast_cli(a->fd,"\t\t\tversion: %s\n", resource->cap->version); 02539 ast_cli(a->fd,"\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 02540 } 02541 ast_cli(a->fd,"\t\tStatus: %d\n", resource->status); 02542 ast_cli(a->fd,"\t\tPriority: %d\n", resource->priority); 02543 } 02544 ASTOBJ_UNLOCK(iterator); 02545 }); 02546 iterator = client; 02547 }); 02548 return CLI_SUCCESS; 02549 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show client status.
Definition at line 2464 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, clients, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.
02465 { 02466 char *status; 02467 int count = 0; 02468 02469 switch (cmd) { 02470 case CLI_INIT: 02471 e->command = "jabber show connected"; 02472 e->usage = 02473 "Usage: jabber show connected\n" 02474 " Shows state of clients and components\n"; 02475 return NULL; 02476 case CLI_GENERATE: 02477 return NULL; 02478 } 02479 02480 ast_cli(a->fd, "Jabber Users and their status:\n"); 02481 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02482 ASTOBJ_RDLOCK(iterator); 02483 count++; 02484 switch (iterator->state) { 02485 case AJI_DISCONNECTED: 02486 status = "Disconnected"; 02487 break; 02488 case AJI_CONNECTING: 02489 status = "Connecting"; 02490 break; 02491 case AJI_CONNECTED: 02492 status = "Connected"; 02493 break; 02494 default: 02495 status = "Unknown"; 02496 } 02497 ast_cli(a->fd, " User: %s - %s\n", iterator->user, status); 02498 ASTOBJ_UNLOCK(iterator); 02499 }); 02500 ast_cli(a->fd, "----\n"); 02501 ast_cli(a->fd, " Number of users: %d\n", count); 02502 return CLI_SUCCESS; 02503 }
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 815 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().
00816 { 00817 iks *x = NULL; 00818 int len; 00819 char *s; 00820 char *base64; 00821 00822 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 00823 iks_start_sasl is an iksemel API function and relies on GnuTLS, 00824 whereas we use OpenSSL */ 00825 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 00826 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 00827 if (!(type & IKS_STREAM_SASL_PLAIN)) { 00828 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 00829 return IKS_NET_NOTSUPP; 00830 } 00831 00832 x = iks_new("auth"); 00833 if (!x) { 00834 ast_log(LOG_ERROR, "Out of memory.\n"); 00835 return IKS_NET_NOTSUPP; 00836 } 00837 00838 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 00839 len = strlen(username) + strlen(pass) + 3; 00840 s = alloca(len); 00841 base64 = alloca((len + 2) * 4 / 3); 00842 iks_insert_attrib(x, "mechanism", "PLAIN"); 00843 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 00844 00845 /* exclude the NULL training byte from the base64 encoding operation 00846 as some XMPP servers will refuse it. 00847 The format for authentication is [authzid]\0authcid\0password 00848 not [authzid]\0authcid\0password\0 */ 00849 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 00850 iks_insert_cdata(x, base64, 0); 00851 ast_aji_send(client, x); 00852 iks_delete(x); 00853 00854 return IKS_OK; 00855 }
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 519 of file res_jabber.c.
References aji_client::p.
Referenced by aji_act_hook().
00520 { 00521 int ret; 00522 00523 /* This is sent not encrypted */ 00524 ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); 00525 if (ret) 00526 return ret; 00527 00528 client->stream_flags |= TRY_SECURE; 00529 return IKS_OK; 00530 }
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 344 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, ast_strdupa, ASTOBJ_CONTAINER_FIND, aji_client::buddies, chan, 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().
00345 { 00346 struct aji_client *client = NULL; 00347 struct aji_buddy *buddy = NULL; 00348 struct aji_resource *r = NULL; 00349 char *s = NULL; 00350 int stat = 7; 00351 char status[2]; 00352 static int deprecation_warning = 0; 00353 AST_DECLARE_APP_ARGS(args, 00354 AST_APP_ARG(sender); 00355 AST_APP_ARG(jid); 00356 AST_APP_ARG(variable); 00357 ); 00358 AST_DECLARE_APP_ARGS(jid, 00359 AST_APP_ARG(screenname); 00360 AST_APP_ARG(resource); 00361 ); 00362 00363 if (deprecation_warning++ % 10 == 0) 00364 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00365 00366 if (!data) { 00367 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<screenname>[/<resource>],<varname>\n"); 00368 return 0; 00369 } 00370 s = ast_strdupa(data); 00371 AST_STANDARD_APP_ARGS(args, s); 00372 00373 if (args.argc != 3) { 00374 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00375 return -1; 00376 } 00377 00378 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00379 00380 if (!(client = ast_aji_get_client(args.sender))) { 00381 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00382 return -1; 00383 } 00384 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00385 if (!buddy) { 00386 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00387 return -1; 00388 } 00389 r = aji_find_resource(buddy, jid.resource); 00390 if (!r && buddy->resources) 00391 r = buddy->resources; 00392 if (!r) 00393 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00394 else 00395 stat = r->status; 00396 snprintf(status, sizeof(status), "%d", stat); 00397 pbx_builtin_setvar_helper(chan, args.variable, status); 00398 return 0; 00399 }
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 2555 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.
02556 { 02557 struct aji_client *client; 02558 struct aji_resource *resource; 02559 const char *name = "asterisk"; 02560 struct aji_message *tmp; 02561 02562 switch (cmd) { 02563 case CLI_INIT: 02564 e->command = "jabber test"; 02565 e->usage = 02566 "Usage: jabber test [client]\n" 02567 " Sends test message for debugging purposes. A specific client\n" 02568 " as configured in jabber.conf can be optionally specified.\n"; 02569 return NULL; 02570 case CLI_GENERATE: 02571 return NULL; 02572 } 02573 02574 if (a->argc > 3) 02575 return CLI_SHOWUSAGE; 02576 else if (a->argc == 3) 02577 name = a->argv[2]; 02578 02579 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 02580 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 02581 return CLI_FAILURE; 02582 } 02583 02584 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 02585 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 02586 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02587 ASTOBJ_RDLOCK(iterator); 02588 ast_verbose("User: %s\n", iterator->name); 02589 for (resource = iterator->resources; resource; resource = resource->next) { 02590 ast_verbose("Resource: %s\n", resource->resource); 02591 if(resource->cap) { 02592 ast_verbose(" client: %s\n", resource->cap->parent->node); 02593 ast_verbose(" version: %s\n", resource->cap->version); 02594 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 02595 } 02596 ast_verbose(" Priority: %d\n", resource->priority); 02597 ast_verbose(" Status: %d\n", resource->status); 02598 ast_verbose(" Message: %s\n", S_OR(resource->description,"")); 02599 } 02600 ASTOBJ_UNLOCK(iterator); 02601 }); 02602 ast_verbose("\nOooh a working message stack!\n"); 02603 AST_LIST_LOCK(&client->messages); 02604 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 02605 ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 02606 } 02607 AST_LIST_UNLOCK(&client->messages); 02608 ASTOBJ_UNREF(client, aji_client_destroy); 02609 02610 return CLI_SUCCESS; 02611 }
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 537 of file res_jabber.c.
References aji_send_header(), ast_debug, aji_client::jid, and aji_client::p.
Referenced by aji_act_hook().
00538 { 00539 int ret; 00540 int sock; 00541 00542 ast_debug(1, "Starting TLS handshake\n"); 00543 00544 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 00545 client->ssl_method = SSLv3_method(); 00546 client->ssl_context = SSL_CTX_new(client->ssl_method); 00547 if (!client->ssl_context) 00548 return IKS_NET_TLSFAIL; 00549 00550 /* Create new SSL session */ 00551 client->ssl_session = SSL_new(client->ssl_context); 00552 if (!client->ssl_session) 00553 return IKS_NET_TLSFAIL; 00554 00555 /* Enforce TLS on our XMPP connection */ 00556 sock = iks_fd(client->p); 00557 ret = SSL_set_fd(client->ssl_session, sock); 00558 if (!ret) 00559 return IKS_NET_TLSFAIL; 00560 00561 /* Perform SSL handshake */ 00562 ret = SSL_connect(client->ssl_session); 00563 if (!ret) 00564 return IKS_NET_TLSFAIL; 00565 00566 client->stream_flags &= (~TRY_SECURE); 00567 client->stream_flags |= SECURE; 00568 00569 /* Sent over the established TLS connection */ 00570 ret = aji_send_header(client, client->jid->server); 00571 if (ret != IKS_OK) 00572 return IKS_NET_TLSFAIL; 00573 00574 ast_debug(1, "TLS started with server\n"); 00575 00576 return IKS_OK; 00577 }
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 1814 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01815 { 01816 int res = 0; 01817 iks *iq = NULL; 01818 iq = iks_new("iq"); 01819 01820 if (iq && client) { 01821 iks_insert_attrib(iq, "type", "get"); 01822 iks_insert_attrib(iq, "to", server); 01823 iks_insert_attrib(iq, "id", client->mid); 01824 ast_aji_increment_mid(client->mid); 01825 ast_aji_send(client, iq); 01826 } else 01827 ast_log(LOG_ERROR, "Out of memory.\n"); 01828 01829 iks_delete(iq); 01830 01831 return res; 01832 }
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 2300 of file res_jabber.c.
References aji_client_destroy(), ast_verb, ASTOBJ_UNREF, and aji_client::p.
Referenced by unload_module().
02301 { 02302 if (client) { 02303 ast_verb(4, "JABBER: Disconnecting\n"); 02304 #ifdef HAVE_OPENSSL 02305 if (client->stream_flags & SECURE) { 02306 SSL_shutdown(client->ssl_session); 02307 SSL_CTX_free(client->ssl_context); 02308 SSL_free(client->ssl_session); 02309 } 02310 #endif 02311 iks_disconnect(client->p); 02312 iks_parser_delete(client->p); 02313 ASTOBJ_UNREF(client, aji_client_destroy); 02314 } 02315 02316 return 1; 02317 }
struct aji_client* ast_aji_get_client | ( | const char * | name | ) |
grab a aji_client structure by label name or JID (without the resource string)
name | label or JID |
Definition at line 2921 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, clients, and strsep().
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().
02922 { 02923 struct aji_client *client = NULL; 02924 char *aux = NULL; 02925 02926 client = ASTOBJ_CONTAINER_FIND(&clients, name); 02927 if (!client && strchr(name, '@')) { 02928 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02929 aux = ast_strdupa(iterator->user); 02930 if (strchr(aux, '/')) { 02931 /* strip resource for comparison */ 02932 aux = strsep(&aux, "/"); 02933 } 02934 if (!strncasecmp(aux, name, strlen(aux))) { 02935 client = iterator; 02936 } 02937 }); 02938 } 02939 02940 return client; 02941 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) |
Definition at line 2943 of file res_jabber.c.
References clients.
02944 { 02945 return &clients; 02946 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 1958 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().
01959 { 01960 int i = 0; 01961 01962 for (i = strlen(mid) - 1; i >= 0; i--) { 01963 if (mid[i] != 'z') { 01964 mid[i] = mid[i] + 1; 01965 i = 0; 01966 } else 01967 mid[i] = 'a'; 01968 } 01969 }
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 1871 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01872 { 01873 int res = 0; 01874 iks *invite, *body, *namespace; 01875 01876 invite = iks_new("message"); 01877 body = iks_new("body"); 01878 namespace = iks_new("x"); 01879 if (client && invite && body && namespace) { 01880 iks_insert_attrib(invite, "to", user); 01881 iks_insert_attrib(invite, "id", client->mid); 01882 ast_aji_increment_mid(client->mid); 01883 iks_insert_cdata(body, message, 0); 01884 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 01885 iks_insert_attrib(namespace, "jid", room); 01886 iks_insert_node(invite, body); 01887 iks_insert_node(invite, namespace); 01888 res = ast_aji_send(client, invite); 01889 } else 01890 ast_log(LOG_ERROR, "Out of memory.\n"); 01891 01892 iks_delete(body); 01893 iks_delete(namespace); 01894 iks_delete(invite); 01895 01896 return res; 01897 }
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 1840 of file res_jabber.c.
References ast_aji_send(), ast_log(), and LOG_ERROR.
01841 { 01842 int res = 0; 01843 iks *presence = NULL, *priority = NULL; 01844 presence = iks_new("presence"); 01845 priority = iks_new("priority"); 01846 if (presence && priority && client) { 01847 iks_insert_cdata(priority, "0", 1); 01848 iks_insert_attrib(presence, "to", room); 01849 iks_insert_node(presence, priority); 01850 res = ast_aji_send(client, presence); 01851 iks_insert_cdata(priority, "5", 1); 01852 iks_insert_attrib(presence, "to", room); 01853 res = ast_aji_send(client, presence); 01854 } else 01855 ast_log(LOG_ERROR, "Out of memory.\n"); 01856 01857 iks_delete(presence); 01858 iks_delete(priority); 01859 01860 return res; 01861 }
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 738 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().
00739 { 00740 return aji_send_raw(client, iks_string(iks_stack(x), x)); 00741 }
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 1787 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().
01788 { 01789 int res = 0; 01790 iks *message_packet = NULL; 01791 if (client->state == AJI_CONNECTED) { 01792 message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message); 01793 if (message_packet) { 01794 iks_insert_attrib(message_packet, "from", client->jid->full); 01795 res = ast_aji_send(client, message_packet); 01796 } else { 01797 ast_log(LOG_ERROR, "Out of memory.\n"); 01798 } 01799 01800 iks_delete(message_packet); 01801 } else 01802 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 01803 return 1; 01804 }
static int gtalk_yuck | ( | iks * | node | ) | [static] |
Jabber GTalk function.
node | iks |
Definition at line 302 of file res_jabber.c.
Referenced by aji_handle_presence().
00303 { 00304 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) 00305 return 1; 00306 return 0; 00307 }
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 316 of file res_jabber.c.
References ast_sha1_hash(), and buf.
Referenced by aji_act_hook().
00317 { 00318 iks *x, *y; 00319 x = iks_new("iq"); 00320 iks_insert_attrib(x, "type", "set"); 00321 y = iks_insert(x, "query"); 00322 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00323 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00324 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00325 if (sid) { 00326 char buf[41]; 00327 char sidpass[100]; 00328 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00329 ast_sha1_hash(buf, sidpass); 00330 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00331 } else { 00332 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00333 } 00334 return x; 00335 }
static int load_module | ( | void | ) | [static] |
Unload the jabber module.
Definition at line 3052 of file res_jabber.c.
References aji_cli, aji_reload(), aji_send_exec(), aji_status_exec(), ast_cli_register_multiple(), ast_custom_function_register, ast_manager_register2(), AST_MODULE_LOAD_DECLINE, ast_register_application, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, jabberstatus_function, manager_jabber_send(), and mandescr_jabber_send.
03053 { 03054 ASTOBJ_CONTAINER_INIT(&clients); 03055 if(!aji_reload(0)) 03056 return AST_MODULE_LOAD_DECLINE; 03057 ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, 03058 "Sends a message to a Jabber Client", mandescr_jabber_send); 03059 ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip); 03060 ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip); 03061 ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); 03062 ast_custom_function_register(&jabberstatus_function); 03063 03064 return 0; 03065 }
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 2961 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(), astman_send_error(), and s.
Referenced by load_module().
02962 { 02963 struct aji_client *client = NULL; 02964 const char *id = astman_get_header(m,"ActionID"); 02965 const char *jabber = astman_get_header(m,"Jabber"); 02966 const char *screenname = astman_get_header(m,"ScreenName"); 02967 const char *message = astman_get_header(m,"Message"); 02968 02969 if (ast_strlen_zero(jabber)) { 02970 astman_send_error(s, m, "No transport specified"); 02971 return 0; 02972 } 02973 if (ast_strlen_zero(screenname)) { 02974 astman_send_error(s, m, "No ScreenName specified"); 02975 return 0; 02976 } 02977 if (ast_strlen_zero(message)) { 02978 astman_send_error(s, m, "No Message specified"); 02979 return 0; 02980 } 02981 02982 astman_send_ack(s, m, "Attempting to send Jabber Message"); 02983 client = ast_aji_get_client(jabber); 02984 if (!client) { 02985 astman_send_error(s, m, "Could not find Sender"); 02986 return 0; 02987 } 02988 if (strchr(screenname, '@') && message) { 02989 ast_aji_send_chat(client, screenname, message); 02990 astman_append(s, "Response: Success\r\n"); 02991 } else { 02992 astman_append(s, "Response: Error\r\n"); 02993 } 02994 if (!ast_strlen_zero(id)) { 02995 astman_append(s, "ActionID: %s\r\n",id); 02996 } 02997 astman_append(s, "\r\n"); 02998 return 0; 02999 }
static int reload | ( | void | ) | [static] |
Wrapper for aji_reload.
Definition at line 3068 of file res_jabber.c.
References aji_reload().
03069 { 03070 aji_reload(1); 03071 return 0; 03072 }
static int unload_module | ( | void | ) | [static] |
Unload the jabber module.
Definition at line 3028 of file res_jabber.c.
References aji_cli, aji_client_destroy(), AJI_DISCONNECTING, 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, clients, and jabberstatus_function.
03029 { 03030 03031 ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); 03032 ast_unregister_application(app_ajisend); 03033 ast_unregister_application(app_ajistatus); 03034 ast_manager_unregister("JabberSend"); 03035 ast_custom_function_unregister(&jabberstatus_function); 03036 03037 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03038 ASTOBJ_RDLOCK(iterator); 03039 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 03040 iterator->state = AJI_DISCONNECTING; 03041 ast_aji_disconnect(iterator); 03042 pthread_join(iterator->thread, NULL); 03043 ASTOBJ_UNLOCK(iterator); 03044 }); 03045 03046 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); 03047 ASTOBJ_CONTAINER_DESTROY(&clients); 03048 return 0; 03049 }
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3078 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
char* ajisend_descrip [static] |
Initial value:
"JabberSend(Jabber,ScreenName,Message)\n" " Jabber - Client or transport Asterisk uses to connect to Jabber\n" " ScreenName - XMPP/Jabber JID (Name) of recipient\n" " Message - Message to be sent to the budd (UTF8)y\n"
Definition at line 139 of file res_jabber.c.
char* ajisend_synopsis = "JabberSend(jabber,screenname,message)" [static] |
Definition at line 137 of file res_jabber.c.
char* ajistatus_descrip [static] |
Definition at line 149 of file res_jabber.c.
char* ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)" [static] |
Definition at line 147 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 135 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 145 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3078 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL |
struct ast_cli_entry cli_aji_do_debug_deprecated = { .handler = aji_do_debug_deprecated , .summary = "Enable/disable jabber debugging" ,__VA_ARGS__ } [static] |
Definition at line 126 of file res_jabber.c.
struct aji_client_container clients |
Definition at line 158 of file res_jabber.c.
Referenced by aji_create_client(), aji_do_debug_deprecated(), 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_AUTOPRUNE | AJI_AUTOREGISTER } [static] |
struct ast_custom_function jabberstatus_function [static] |
char mandescr_jabber_send[] [static] |