#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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct ast_cli_entry | aji_cli [] |
static char * | ajisend_descrip |
static char * | ajisend_synopsis = "JabberSend(jabber,screenname,message)" |
static char * | ajistatus_descrip |
static char * | ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)" |
static char * | app_ajisend = "JabberSend" |
static char * | app_ajistatus = "JabberStatus" |
static const struct ast_module_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_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 3083 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 3083 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 868 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().
00869 { 00870 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00871 ikspak *pak = NULL; 00872 iks *auth = NULL; 00873 int features = 0; 00874 00875 if(!node) { 00876 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 00877 ASTOBJ_UNREF(client, aji_client_destroy); 00878 return IKS_HOOK; 00879 } 00880 00881 if (client->state == AJI_DISCONNECTING) { 00882 ASTOBJ_UNREF(client, aji_client_destroy); 00883 return IKS_HOOK; 00884 } 00885 00886 pak = iks_packet(node); 00887 00888 if (!client->component) { /*client */ 00889 switch (type) { 00890 case IKS_NODE_START: 00891 if (client->usetls && !aji_is_secure(client)) { 00892 #ifndef HAVE_OPENSSL 00893 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"); 00894 ASTOBJ_UNREF(client, aji_client_destroy); 00895 return IKS_HOOK; 00896 #else 00897 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 00898 ast_log(LOG_ERROR, "Could not start TLS\n"); 00899 ASTOBJ_UNREF(client, aji_client_destroy); 00900 return IKS_HOOK; 00901 } 00902 #endif 00903 break; 00904 } 00905 if (!client->usesasl) { 00906 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); 00907 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 00908 if (auth) { 00909 iks_insert_attrib(auth, "id", client->mid); 00910 iks_insert_attrib(auth, "to", client->jid->server); 00911 ast_aji_increment_mid(client->mid); 00912 ast_aji_send(client, auth); 00913 iks_delete(auth); 00914 } else 00915 ast_log(LOG_ERROR, "Out of memory.\n"); 00916 } 00917 break; 00918 00919 case IKS_NODE_NORMAL: 00920 #ifdef HAVE_OPENSSL 00921 if (client->stream_flags & TRY_SECURE) { 00922 if (!strcmp("proceed", iks_name(node))) { 00923 return aji_tls_handshake(client); 00924 } 00925 } 00926 #endif 00927 if (!strcmp("stream:features", iks_name(node))) { 00928 features = iks_stream_features(node); 00929 if (client->usesasl) { 00930 if (client->usetls && !aji_is_secure(client)) 00931 break; 00932 if (client->authorized) { 00933 if (features & IKS_STREAM_BIND) { 00934 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); 00935 auth = iks_make_resource_bind(client->jid); 00936 if (auth) { 00937 iks_insert_attrib(auth, "id", client->mid); 00938 ast_aji_increment_mid(client->mid); 00939 ast_aji_send(client, auth); 00940 iks_delete(auth); 00941 } else { 00942 ast_log(LOG_ERROR, "Out of memory.\n"); 00943 break; 00944 } 00945 } 00946 if (features & IKS_STREAM_SESSION) { 00947 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); 00948 auth = iks_make_session(); 00949 if (auth) { 00950 iks_insert_attrib(auth, "id", "auth"); 00951 ast_aji_increment_mid(client->mid); 00952 ast_aji_send(client, auth); 00953 iks_delete(auth); 00954 } else { 00955 ast_log(LOG_ERROR, "Out of memory.\n"); 00956 } 00957 } 00958 } else { 00959 int ret; 00960 if (!client->jid->user) { 00961 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 00962 break; 00963 } 00964 00965 ret = aji_start_sasl(client, features, client->jid->user, client->password); 00966 if (ret != IKS_OK) { 00967 ASTOBJ_UNREF(client, aji_client_destroy); 00968 return IKS_HOOK; 00969 } 00970 break; 00971 } 00972 } 00973 } else if (!strcmp("failure", iks_name(node))) { 00974 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 00975 } else if (!strcmp("success", iks_name(node))) { 00976 client->authorized = 1; 00977 aji_send_header(client, client->jid->server); 00978 } 00979 break; 00980 case IKS_NODE_ERROR: 00981 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 00982 ASTOBJ_UNREF(client, aji_client_destroy); 00983 return IKS_HOOK; 00984 break; 00985 case IKS_NODE_STOP: 00986 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 00987 ASTOBJ_UNREF(client, aji_client_destroy); 00988 return IKS_HOOK; 00989 break; 00990 } 00991 } else if (client->state != AJI_CONNECTED && client->component) { 00992 switch (type) { 00993 case IKS_NODE_START: 00994 if (client->state == AJI_DISCONNECTED) { 00995 char secret[160], shasum[320], *handshake; 00996 00997 sprintf(secret, "%s%s", pak->id, client->password); 00998 ast_sha1_hash(shasum, secret); 00999 handshake = NULL; 01000 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01001 aji_send_raw(client, handshake); 01002 ast_free(handshake); 01003 handshake = NULL; 01004 } 01005 client->state = AJI_CONNECTING; 01006 if(aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01007 client->state = AJI_CONNECTED; 01008 else 01009 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01010 break; 01011 } 01012 break; 01013 01014 case IKS_NODE_NORMAL: 01015 break; 01016 01017 case IKS_NODE_ERROR: 01018 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01019 ASTOBJ_UNREF(client, aji_client_destroy); 01020 return IKS_HOOK; 01021 01022 case IKS_NODE_STOP: 01023 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01024 ASTOBJ_UNREF(client, aji_client_destroy); 01025 return IKS_HOOK; 01026 } 01027 } 01028 01029 switch (pak->type) { 01030 case IKS_PAK_NONE: 01031 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01032 break; 01033 case IKS_PAK_MESSAGE: 01034 aji_handle_message(client, pak); 01035 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01036 break; 01037 case IKS_PAK_PRESENCE: 01038 aji_handle_presence(client, pak); 01039 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01040 break; 01041 case IKS_PAK_S10N: 01042 aji_handle_subscribe(client, pak); 01043 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01044 break; 01045 case IKS_PAK_IQ: 01046 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01047 aji_handle_iq(client, node); 01048 break; 01049 default: 01050 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01051 break; 01052 } 01053 01054 iks_filter_packet(client->f, pak); 01055 01056 if (node) 01057 iks_delete(node); 01058 01059 ASTOBJ_UNREF(client, aji_client_destroy); 01060 return IKS_OK; 01061 }
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 2251 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().
02252 { 02253 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02254 int res = 0; 02255 02256 if (client) { 02257 if (client->state == AJI_DISCONNECTED) { 02258 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); 02259 client->state = AJI_CONNECTING; 02260 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 02261 iks_filter_remove_hook(client->f, aji_client_connect); 02262 if(!client->component) /*client*/ 02263 aji_get_roster(client); 02264 } 02265 } else 02266 ast_log(LOG_ERROR, "Out of memory.\n"); 02267 02268 ASTOBJ_UNREF(client, aji_client_destroy); 02269 return res; 02270 }
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 1277 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().
01278 { 01279 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01280 struct aji_resource *resource = NULL; 01281 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01282 01283 resource = aji_find_resource(buddy, pak->from->resource); 01284 if (pak->subtype == IKS_TYPE_RESULT) { 01285 if (!resource) { 01286 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 01287 ASTOBJ_UNREF(client, aji_client_destroy); 01288 return IKS_FILTER_EAT; 01289 } 01290 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01291 resource->cap->jingle = 1; 01292 } else 01293 resource->cap->jingle = 0; 01294 } else if (pak->subtype == IKS_TYPE_GET) { 01295 iks *iq, *disco, *ident, *google, *query; 01296 iq = iks_new("iq"); 01297 query = iks_new("query"); 01298 ident = iks_new("identity"); 01299 disco = iks_new("feature"); 01300 google = iks_new("feature"); 01301 if (iq && ident && disco && google) { 01302 iks_insert_attrib(iq, "from", client->jid->full); 01303 iks_insert_attrib(iq, "to", pak->from->full); 01304 iks_insert_attrib(iq, "type", "result"); 01305 iks_insert_attrib(iq, "id", pak->id); 01306 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01307 iks_insert_attrib(ident, "category", "client"); 01308 iks_insert_attrib(ident, "type", "pc"); 01309 iks_insert_attrib(ident, "name", "asterisk"); 01310 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 01311 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 01312 iks_insert_node(iq, query); 01313 iks_insert_node(query, ident); 01314 iks_insert_node(query, google); 01315 iks_insert_node(query, disco); 01316 ast_aji_send(client, iq); 01317 } else 01318 ast_log(LOG_ERROR, "Out of Memory.\n"); 01319 01320 iks_delete(iq); 01321 iks_delete(query); 01322 iks_delete(ident); 01323 iks_delete(google); 01324 iks_delete(disco); 01325 } else if (pak->subtype == IKS_TYPE_ERROR) { 01326 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 01327 } 01328 ASTOBJ_UNREF(client, aji_client_destroy); 01329 return IKS_FILTER_EAT; 01330 }
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 2852 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 2624 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.
02625 { 02626 char *resource; 02627 struct aji_client *client = NULL; 02628 int flag = 0; 02629 02630 client = ASTOBJ_CONTAINER_FIND(&clients,label); 02631 if (!client) { 02632 flag = 1; 02633 client = ast_calloc(1, sizeof(*client)); 02634 if (!client) { 02635 ast_log(LOG_ERROR, "Out of memory!\n"); 02636 return 0; 02637 } 02638 ASTOBJ_INIT(client); 02639 ASTOBJ_WRLOCK(client); 02640 ASTOBJ_CONTAINER_INIT(&client->buddies); 02641 } else { 02642 ASTOBJ_WRLOCK(client); 02643 ASTOBJ_UNMARK(client); 02644 } 02645 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 02646 ast_copy_string(client->name, label, sizeof(client->name)); 02647 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 02648 02649 /* Set default values for the client object */ 02650 client->debug = debug; 02651 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 02652 client->port = 5222; 02653 client->usetls = 1; 02654 client->usesasl = 1; 02655 client->forcessl = 0; 02656 client->keepalive = 1; 02657 client->timeout = 50; 02658 client->message_timeout = 100; 02659 AST_LIST_HEAD_INIT(&client->messages); 02660 client->component = 0; 02661 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 02662 client->priority = 0; 02663 client->status = IKS_SHOW_AVAILABLE; 02664 02665 if (flag) { 02666 client->authorized = 0; 02667 client->state = AJI_DISCONNECTED; 02668 } 02669 while (var) { 02670 if (!strcasecmp(var->name, "username")) 02671 ast_copy_string(client->user, var->value, sizeof(client->user)); 02672 else if (!strcasecmp(var->name, "serverhost")) 02673 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 02674 else if (!strcasecmp(var->name, "secret")) 02675 ast_copy_string(client->password, var->value, sizeof(client->password)); 02676 else if (!strcasecmp(var->name, "statusmessage")) 02677 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 02678 else if (!strcasecmp(var->name, "port")) 02679 client->port = atoi(var->value); 02680 else if (!strcasecmp(var->name, "timeout")) 02681 client->message_timeout = atoi(var->value); 02682 else if (!strcasecmp(var->name, "debug")) 02683 client->debug = (ast_false(var->value)) ? 0 : 1; 02684 else if (!strcasecmp(var->name, "type")) { 02685 if (!strcasecmp(var->value, "component")) 02686 client->component = 1; 02687 } else if (!strcasecmp(var->name, "usetls")) { 02688 client->usetls = (ast_false(var->value)) ? 0 : 1; 02689 } else if (!strcasecmp(var->name, "usesasl")) { 02690 client->usesasl = (ast_false(var->value)) ? 0 : 1; 02691 } else if (!strcasecmp(var->name, "forceoldssl")) 02692 client->forcessl = (ast_false(var->value)) ? 0 : 1; 02693 else if (!strcasecmp(var->name, "keepalive")) 02694 client->keepalive = (ast_false(var->value)) ? 0 : 1; 02695 else if (!strcasecmp(var->name, "autoprune")) 02696 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 02697 else if (!strcasecmp(var->name, "autoregister")) 02698 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 02699 else if (!strcasecmp(var->name, "buddy")) 02700 aji_create_buddy((char *)var->value, client); 02701 else if (!strcasecmp(var->name, "priority")) 02702 client->priority = atoi(var->value); 02703 else if (!strcasecmp(var->name, "status")) { 02704 if (!strcasecmp(var->value, "unavailable")) 02705 client->status = IKS_SHOW_UNAVAILABLE; 02706 else 02707 if (!strcasecmp(var->value, "available") 02708 || !strcasecmp(var->value, "online")) 02709 client->status = IKS_SHOW_AVAILABLE; 02710 else 02711 if (!strcasecmp(var->value, "chat") 02712 || !strcasecmp(var->value, "chatty")) 02713 client->status = IKS_SHOW_CHAT; 02714 else 02715 if (!strcasecmp(var->value, "away")) 02716 client->status = IKS_SHOW_AWAY; 02717 else 02718 if (!strcasecmp(var->value, "xa") 02719 || !strcasecmp(var->value, "xaway")) 02720 client->status = IKS_SHOW_XA; 02721 else 02722 if (!strcasecmp(var->value, "dnd")) 02723 client->status = IKS_SHOW_DND; 02724 else 02725 if (!strcasecmp(var->value, "invisible")) 02726 #ifdef IKS_SHOW_INVISIBLE 02727 client->status = IKS_SHOW_INVISIBLE; 02728 #else 02729 { 02730 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 02731 client->status = IKS_SHOW_DND; 02732 } 02733 #endif 02734 else 02735 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 02736 } 02737 /* no transport support in this version */ 02738 /* else if (!strcasecmp(var->name, "transport")) 02739 aji_create_transport(var->value, client); 02740 */ 02741 var = var->next; 02742 } 02743 if (!flag) { 02744 ASTOBJ_UNLOCK(client); 02745 ASTOBJ_UNREF(client, aji_client_destroy); 02746 return 1; 02747 } 02748 02749 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 02750 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 02751 if (!client->p) { 02752 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 02753 return 0; 02754 } 02755 client->stack = iks_stack_new(8192, 8192); 02756 if (!client->stack) { 02757 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 02758 return 0; 02759 } 02760 client->f = iks_filter_new(); 02761 if (!client->f) { 02762 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 02763 return 0; 02764 } 02765 if (!strchr(client->user, '/') && !client->component) { /*client */ 02766 resource = NULL; 02767 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02768 client->jid = iks_id_new(client->stack, resource); 02769 ast_free(resource); 02770 } 02771 } else 02772 client->jid = iks_id_new(client->stack, client->user); 02773 if (client->component) { 02774 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02775 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 02776 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); 02777 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); 02778 } else { 02779 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02780 } 02781 if (!strchr(client->user, '/') && !client->component) { /*client */ 02782 resource = NULL; 02783 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02784 client->jid = iks_id_new(client->stack, resource); 02785 ast_free(resource); 02786 } 02787 } else 02788 client->jid = iks_id_new(client->stack, client->user); 02789 iks_set_log_hook(client->p, aji_log_hook); 02790 ASTOBJ_UNLOCK(client); 02791 ASTOBJ_CONTAINER_LINK(&clients,client); 02792 return 1; 02793 }
static int aji_dinfo_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handler of the return info packet.
data | aji_client | |
pak | ikspak |
Definition at line 1337 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().
01338 { 01339 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01340 char *node = NULL; 01341 struct aji_resource *resource = NULL; 01342 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01343 01344 resource = aji_find_resource(buddy, pak->from->resource); 01345 if (pak->subtype == IKS_TYPE_ERROR) { 01346 ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n"); 01347 return IKS_FILTER_EAT; 01348 } 01349 if (pak->subtype == IKS_TYPE_RESULT) { 01350 if (!resource) { 01351 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); 01352 ASTOBJ_UNREF(client, aji_client_destroy); 01353 return IKS_FILTER_EAT; 01354 } 01355 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01356 resource->cap->jingle = 1; 01357 } else 01358 resource->cap->jingle = 0; 01359 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 01360 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 01361 01362 iq = iks_new("iq"); 01363 query = iks_new("query"); 01364 identity = iks_new("identity"); 01365 disco = iks_new("feature"); 01366 reg = iks_new("feature"); 01367 commands = iks_new("feature"); 01368 gateway = iks_new("feature"); 01369 version = iks_new("feature"); 01370 vcard = iks_new("feature"); 01371 search = iks_new("feature"); 01372 01373 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 01374 iks_insert_attrib(iq, "from", client->user); 01375 iks_insert_attrib(iq, "to", pak->from->full); 01376 iks_insert_attrib(iq, "id", pak->id); 01377 iks_insert_attrib(iq, "type", "result"); 01378 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01379 iks_insert_attrib(identity, "category", "gateway"); 01380 iks_insert_attrib(identity, "type", "pstn"); 01381 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 01382 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 01383 iks_insert_attrib(reg, "var", "jabber:iq:register"); 01384 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 01385 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 01386 iks_insert_attrib(version, "var", "jabber:iq:version"); 01387 iks_insert_attrib(vcard, "var", "vcard-temp"); 01388 iks_insert_attrib(search, "var", "jabber:iq:search"); 01389 01390 iks_insert_node(iq, query); 01391 iks_insert_node(query, identity); 01392 iks_insert_node(query, disco); 01393 iks_insert_node(query, reg); 01394 iks_insert_node(query, commands); 01395 iks_insert_node(query, gateway); 01396 iks_insert_node(query, version); 01397 iks_insert_node(query, vcard); 01398 iks_insert_node(query, search); 01399 ast_aji_send(client, iq); 01400 } else { 01401 ast_log(LOG_ERROR, "Out of memory.\n"); 01402 } 01403 01404 iks_delete(iq); 01405 iks_delete(query); 01406 iks_delete(identity); 01407 iks_delete(disco); 01408 iks_delete(reg); 01409 iks_delete(commands); 01410 iks_delete(gateway); 01411 iks_delete(version); 01412 iks_delete(vcard); 01413 iks_delete(search); 01414 01415 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 01416 iks *iq, *query, *confirm; 01417 iq = iks_new("iq"); 01418 query = iks_new("query"); 01419 confirm = iks_new("item"); 01420 01421 if (iq && query && confirm && client) { 01422 iks_insert_attrib(iq, "from", client->user); 01423 iks_insert_attrib(iq, "to", pak->from->full); 01424 iks_insert_attrib(iq, "id", pak->id); 01425 iks_insert_attrib(iq, "type", "result"); 01426 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01427 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01428 iks_insert_attrib(confirm, "node", "confirmaccount"); 01429 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01430 iks_insert_attrib(confirm, "jid", client->user); 01431 iks_insert_node(iq, query); 01432 iks_insert_node(query, confirm); 01433 ast_aji_send(client, iq); 01434 } else { 01435 ast_log(LOG_ERROR, "Out of memory.\n"); 01436 } 01437 01438 iks_delete(iq); 01439 iks_delete(query); 01440 iks_delete(confirm); 01441 01442 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 01443 iks *iq, *query, *feature; 01444 01445 iq = iks_new("iq"); 01446 query = iks_new("query"); 01447 feature = iks_new("feature"); 01448 01449 if (iq && query && feature && client) { 01450 iks_insert_attrib(iq, "from", client->user); 01451 iks_insert_attrib(iq, "to", pak->from->full); 01452 iks_insert_attrib(iq, "id", pak->id); 01453 iks_insert_attrib(iq, "type", "result"); 01454 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01455 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01456 iks_insert_node(iq, query); 01457 iks_insert_node(query, feature); 01458 ast_aji_send(client, iq); 01459 } else { 01460 ast_log(LOG_ERROR, "Out of memory.\n"); 01461 } 01462 01463 iks_delete(iq); 01464 iks_delete(query); 01465 iks_delete(feature); 01466 } 01467 01468 ASTOBJ_UNREF(client, aji_client_destroy); 01469 return IKS_FILTER_EAT; 01470 }
static int aji_ditems_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handles stuff.
data | void | |
pak | ikspak |
Definition at line 1182 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().
01183 { 01184 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01185 char *node = NULL; 01186 01187 if (!(node = iks_find_attrib(pak->query, "node"))) { 01188 iks *iq = NULL, *query = NULL, *item = NULL; 01189 iq = iks_new("iq"); 01190 query = iks_new("query"); 01191 item = iks_new("item"); 01192 01193 if (iq && query && item) { 01194 iks_insert_attrib(iq, "from", client->user); 01195 iks_insert_attrib(iq, "to", pak->from->full); 01196 iks_insert_attrib(iq, "id", pak->id); 01197 iks_insert_attrib(iq, "type", "result"); 01198 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01199 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01200 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01201 iks_insert_attrib(item, "jid", client->user); 01202 01203 iks_insert_node(iq, query); 01204 iks_insert_node(query, item); 01205 ast_aji_send(client, iq); 01206 } else { 01207 ast_log(LOG_ERROR, "Out of memory.\n"); 01208 } 01209 01210 iks_delete(iq); 01211 iks_delete(query); 01212 iks_delete(item); 01213 01214 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01215 iks *iq, *query, *confirm; 01216 iq = iks_new("iq"); 01217 query = iks_new("query"); 01218 confirm = iks_new("item"); 01219 if (iq && query && confirm && client) { 01220 iks_insert_attrib(iq, "from", client->user); 01221 iks_insert_attrib(iq, "to", pak->from->full); 01222 iks_insert_attrib(iq, "id", pak->id); 01223 iks_insert_attrib(iq, "type", "result"); 01224 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01225 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01226 iks_insert_attrib(confirm, "node", "confirmaccount"); 01227 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01228 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01229 01230 iks_insert_node(iq, query); 01231 iks_insert_node(query, confirm); 01232 ast_aji_send(client, iq); 01233 } else { 01234 ast_log(LOG_ERROR, "Out of memory.\n"); 01235 } 01236 01237 iks_delete(iq); 01238 iks_delete(query); 01239 iks_delete(confirm); 01240 01241 } else if (!strcasecmp(node, "confirmaccount")) { 01242 iks *iq = NULL, *query = NULL, *feature = NULL; 01243 01244 iq = iks_new("iq"); 01245 query = iks_new("query"); 01246 feature = iks_new("feature"); 01247 01248 if (iq && query && feature && client) { 01249 iks_insert_attrib(iq, "from", client->user); 01250 iks_insert_attrib(iq, "to", pak->from->full); 01251 iks_insert_attrib(iq, "id", pak->id); 01252 iks_insert_attrib(iq, "type", "result"); 01253 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01254 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01255 iks_insert_node(iq, query); 01256 iks_insert_node(query, feature); 01257 ast_aji_send(client, iq); 01258 } else { 01259 ast_log(LOG_ERROR, "Out of memory.\n"); 01260 } 01261 01262 iks_delete(iq); 01263 iks_delete(query); 01264 iks_delete(feature); 01265 } 01266 01267 ASTOBJ_UNREF(client, aji_client_destroy); 01268 return IKS_FILTER_EAT; 01269 01270 }
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 2406 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.
02407 { 02408 02409 switch (cmd) { 02410 case CLI_INIT: 02411 e->command = "jabber debug [off]"; 02412 e->usage = 02413 "Usage: jabber debug [off]\n" 02414 " Enables/disables dumping of Jabber packets for debugging purposes.\n"; 02415 return NULL; 02416 case CLI_GENERATE: 02417 return NULL; 02418 } 02419 02420 if (a->argc == 2) { 02421 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02422 ASTOBJ_RDLOCK(iterator); 02423 iterator->debug = 1; 02424 ASTOBJ_UNLOCK(iterator); 02425 }); 02426 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02427 return CLI_SUCCESS; 02428 } else if (a->argc == 3) { 02429 if (!strncasecmp(a->argv[2], "off", 3)) { 02430 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02431 ASTOBJ_RDLOCK(iterator); 02432 iterator->debug = 0; 02433 ASTOBJ_UNLOCK(iterator); 02434 }); 02435 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02436 return CLI_SUCCESS; 02437 } 02438 } 02439 return CLI_SHOWUSAGE; /* defaults to invalid */ 02440 }
static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Reload jabber module.
Definition at line 2446 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.
02447 { 02448 switch (cmd) { 02449 case CLI_INIT: 02450 e->command = "jabber reload"; 02451 e->usage = 02452 "Usage: jabber reload\n" 02453 " Reloads the Jabber module.\n"; 02454 return NULL; 02455 case CLI_GENERATE: 02456 return NULL; 02457 } 02458 02459 aji_reload(1); 02460 ast_cli(a->fd, "Jabber Reloaded.\n"); 02461 return CLI_SUCCESS; 02462 }
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 2366 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.
02367 { 02368 switch (cmd) { 02369 case CLI_INIT: 02370 e->command = "jabber set debug {on|off}"; 02371 e->usage = 02372 "Usage: jabber set debug {on|off}\n" 02373 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 02374 return NULL; 02375 case CLI_GENERATE: 02376 return NULL; 02377 } 02378 02379 if (a->argc != e->args) 02380 return CLI_SHOWUSAGE; 02381 02382 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 02383 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02384 ASTOBJ_RDLOCK(iterator); 02385 iterator->debug = 1; 02386 ASTOBJ_UNLOCK(iterator); 02387 }); 02388 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02389 return CLI_SUCCESS; 02390 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 02391 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02392 ASTOBJ_RDLOCK(iterator); 02393 iterator->debug = 0; 02394 ASTOBJ_UNLOCK(iterator); 02395 }); 02396 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02397 return CLI_SUCCESS; 02398 } 02399 return CLI_SHOWUSAGE; /* defaults to invalid */ 02400 }
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 2124 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().
02125 { 02126 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02127 int flag = 0; 02128 iks *x = NULL; 02129 struct aji_buddy *buddy; 02130 02131 client->state = AJI_CONNECTED; 02132 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02133 ASTOBJ_RDLOCK(iterator); 02134 x = iks_child(pak->query); 02135 flag = 0; 02136 while (x) { 02137 if (!iks_strcmp(iks_name(x), "item")) { 02138 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02139 flag = 1; 02140 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02141 } 02142 } 02143 x = iks_next(x); 02144 } 02145 if (!flag) 02146 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02147 iks_delete(x); 02148 02149 ASTOBJ_UNLOCK(iterator); 02150 }); 02151 02152 x = iks_child(pak->query); 02153 while (x) { 02154 flag = 0; 02155 if (iks_strcmp(iks_name(x), "item") == 0) { 02156 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02157 ASTOBJ_RDLOCK(iterator); 02158 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02159 flag = 1; 02160 ASTOBJ_UNLOCK(iterator); 02161 }); 02162 02163 if (flag) { 02164 /* found buddy, don't create a new one */ 02165 x = iks_next(x); 02166 continue; 02167 } 02168 02169 buddy = ast_calloc(1, sizeof(*buddy)); 02170 if (!buddy) { 02171 ast_log(LOG_WARNING, "Out of memory\n"); 02172 return 0; 02173 } 02174 ASTOBJ_INIT(buddy); 02175 ASTOBJ_WRLOCK(buddy); 02176 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02177 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02178 if(ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02179 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 02180 ASTOBJ_MARK(buddy); 02181 } else if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 02182 /* subscribe to buddy's presence only 02183 if we really need to */ 02184 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 02185 } 02186 ASTOBJ_UNLOCK(buddy); 02187 if (buddy) { 02188 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 02189 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02190 } 02191 } 02192 x = iks_next(x); 02193 } 02194 02195 iks_delete(x); 02196 aji_pruneregister(client); 02197 02198 ASTOBJ_UNREF(client, aji_client_destroy); 02199 return IKS_FILTER_EAT; 02200 }
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 2229 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().
02230 { 02231 iks *roster = NULL; 02232 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 02233 02234 if(roster) { 02235 iks_insert_attrib(roster, "id", "roster"); 02236 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 02237 ast_aji_send(client, roster); 02238 } 02239 02240 iks_delete(roster); 02241 02242 return 1; 02243 }
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 1478 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 1488 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().
01489 { 01490 struct aji_message *insert, *tmp; 01491 int flag = 0; 01492 01493 if (!(insert = ast_calloc(1, sizeof(*insert)))) 01494 return; 01495 time(&insert->arrived); 01496 if (iks_find_cdata(pak->x, "body")) 01497 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 01498 if (pak->id) 01499 ast_copy_string(insert->id, pak->id, sizeof(insert->message)); 01500 if (pak->from) 01501 insert->from = ast_strdup(pak->from->full); 01502 AST_LIST_LOCK(&client->messages); 01503 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 01504 if (flag) { 01505 AST_LIST_REMOVE_CURRENT(list); 01506 if (tmp->from) 01507 ast_free(tmp->from); 01508 if (tmp->message) 01509 ast_free(tmp->message); 01510 } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) { 01511 flag = 1; 01512 AST_LIST_REMOVE_CURRENT(list); 01513 if (tmp->from) 01514 ast_free(tmp->from); 01515 if (tmp->message) 01516 ast_free(tmp->message); 01517 } 01518 } 01519 AST_LIST_TRAVERSE_SAFE_END; 01520 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 01521 AST_LIST_UNLOCK(&client->messages); 01522 }
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 1528 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().
01529 { 01530 int status, priority; 01531 struct aji_buddy *buddy; 01532 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 01533 char *ver, *node, *descrip, *type; 01534 01535 if(client->state != AJI_CONNECTED) 01536 aji_create_buddy(pak->from->partial, client); 01537 01538 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01539 if (!buddy && pak->from->partial) { 01540 /* allow our jid to be used to log in with another resource */ 01541 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 01542 aji_create_buddy(pak->from->partial, client); 01543 else 01544 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 01545 return; 01546 } 01547 type = iks_find_attrib(pak->x, "type"); 01548 if(client->component && type &&!strcasecmp("probe", type)) { 01549 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01550 ast_verbose("what i was looking for \n"); 01551 } 01552 ASTOBJ_WRLOCK(buddy); 01553 status = (pak->show) ? pak->show : 6; 01554 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 01555 tmp = buddy->resources; 01556 descrip = ast_strdup(iks_find_cdata(pak->x,"status")); 01557 01558 while (tmp && pak->from->resource) { 01559 if (!strcasecmp(tmp->resource, pak->from->resource)) { 01560 tmp->status = status; 01561 if (tmp->description) ast_free(tmp->description); 01562 tmp->description = descrip; 01563 found = tmp; 01564 if (status == 6) { /* Sign off Destroy resource */ 01565 if (last && found->next) { 01566 last->next = found->next; 01567 } else if (!last) { 01568 if (found->next) 01569 buddy->resources = found->next; 01570 else 01571 buddy->resources = NULL; 01572 } else if (!found->next) { 01573 if (last) 01574 last->next = NULL; 01575 else 01576 buddy->resources = NULL; 01577 } 01578 ast_free(found); 01579 found = NULL; 01580 break; 01581 } 01582 /* resource list is sorted by descending priority */ 01583 if (tmp->priority != priority) { 01584 found->priority = priority; 01585 if (!last && !found->next) 01586 /* resource was found to be unique, 01587 leave loop */ 01588 break; 01589 /* search for resource in our list 01590 and take it out for the moment */ 01591 if (last) 01592 last->next = found->next; 01593 else 01594 buddy->resources = found->next; 01595 01596 last = NULL; 01597 tmp = buddy->resources; 01598 if (!buddy->resources) 01599 buddy->resources = found; 01600 /* priority processing */ 01601 while (tmp) { 01602 /* insert resource back according to 01603 its priority value */ 01604 if (found->priority > tmp->priority) { 01605 if (last) 01606 /* insert within list */ 01607 last->next = found; 01608 found->next = tmp; 01609 if (!last) 01610 /* insert on top */ 01611 buddy->resources = found; 01612 break; 01613 } 01614 if (!tmp->next) { 01615 /* insert at the end of the list */ 01616 tmp->next = found; 01617 found->next = NULL; 01618 break; 01619 } 01620 last = tmp; 01621 tmp = tmp->next; 01622 } 01623 } 01624 break; 01625 } 01626 last = tmp; 01627 tmp = tmp->next; 01628 } 01629 01630 /* resource not found in our list, create it */ 01631 if (!found && status != 6 && pak->from->resource) { 01632 found = ast_calloc(1, sizeof(*found)); 01633 01634 if (!found) { 01635 ast_log(LOG_ERROR, "Out of memory!\n"); 01636 return; 01637 } 01638 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 01639 found->status = status; 01640 found->description = descrip; 01641 found->priority = priority; 01642 found->next = NULL; 01643 last = NULL; 01644 tmp = buddy->resources; 01645 while (tmp) { 01646 if (found->priority > tmp->priority) { 01647 if (last) 01648 last->next = found; 01649 found->next = tmp; 01650 if (!last) 01651 buddy->resources = found; 01652 break; 01653 } 01654 if (!tmp->next) { 01655 tmp->next = found; 01656 break; 01657 } 01658 last = tmp; 01659 tmp = tmp->next; 01660 } 01661 if (!tmp) 01662 buddy->resources = found; 01663 } 01664 01665 ASTOBJ_UNLOCK(buddy); 01666 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 01667 01668 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 01669 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 01670 01671 /* handle gmail client's special caps:c tag */ 01672 if (!node && !ver) { 01673 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 01674 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 01675 } 01676 01677 /* retrieve capabilites of the new resource */ 01678 if(status !=6 && found && !found->cap) { 01679 found->cap = aji_find_version(node, ver, pak); 01680 if(gtalk_yuck(pak->x)) /* gtalk should do discover */ 01681 found->cap->jingle = 1; 01682 if(found->cap->jingle && option_debug > 4) { 01683 ast_debug(1,"Special case for google till they support discover.\n"); 01684 } 01685 else { 01686 iks *iq, *query; 01687 iq = iks_new("iq"); 01688 query = iks_new("query"); 01689 if(query && iq) { 01690 iks_insert_attrib(iq, "type", "get"); 01691 iks_insert_attrib(iq, "to", pak->from->full); 01692 iks_insert_attrib(iq,"from", client->jid->full); 01693 iks_insert_attrib(iq, "id", client->mid); 01694 ast_aji_increment_mid(client->mid); 01695 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01696 iks_insert_node(iq, query); 01697 ast_aji_send(client, iq); 01698 01699 } else 01700 ast_log(LOG_ERROR, "Out of memory.\n"); 01701 01702 iks_delete(query); 01703 iks_delete(iq); 01704 } 01705 } 01706 switch (pak->subtype) { 01707 case IKS_TYPE_AVAILABLE: 01708 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 01709 break; 01710 case IKS_TYPE_UNAVAILABLE: 01711 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 01712 break; 01713 default: 01714 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 01715 } 01716 switch (pak->show) { 01717 case IKS_SHOW_UNAVAILABLE: 01718 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01719 break; 01720 case IKS_SHOW_AVAILABLE: 01721 ast_debug(3, "JABBER: type is available\n"); 01722 break; 01723 case IKS_SHOW_CHAT: 01724 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01725 break; 01726 case IKS_SHOW_AWAY: 01727 ast_debug(3, "JABBER: type is away\n"); 01728 break; 01729 case IKS_SHOW_XA: 01730 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01731 break; 01732 case IKS_SHOW_DND: 01733 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01734 break; 01735 default: 01736 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 01737 } 01738 }
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 1746 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().
01747 { 01748 iks *presence = NULL, *status = NULL; 01749 struct aji_buddy* buddy = NULL; 01750 01751 switch (pak->subtype) { 01752 case IKS_TYPE_SUBSCRIBE: 01753 presence = iks_new("presence"); 01754 status = iks_new("status"); 01755 if (presence && status) { 01756 iks_insert_attrib(presence, "type", "subscribed"); 01757 iks_insert_attrib(presence, "to", pak->from->full); 01758 iks_insert_attrib(presence, "from", client->jid->full); 01759 if (pak->id) 01760 iks_insert_attrib(presence, "id", pak->id); 01761 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 01762 iks_insert_node(presence, status); 01763 ast_aji_send(client, presence); 01764 } else 01765 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 01766 01767 iks_delete(presence); 01768 iks_delete(status); 01769 01770 if (client->component) 01771 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01772 case IKS_TYPE_SUBSCRIBED: 01773 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01774 if (!buddy && pak->from->partial) { 01775 aji_create_buddy(pak->from->partial, client); 01776 } 01777 default: 01778 if (option_verbose > 4) { 01779 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 01780 } 01781 } 01782 }
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 2277 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().
02278 { 02279 int connected = IKS_NET_NOCONN; 02280 02281 #ifdef HAVE_OPENSSL 02282 /* reset stream flags */ 02283 client->stream_flags = 0; 02284 #endif 02285 /* If it's a component, connect to user, otherwise, connect to server */ 02286 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 02287 02288 if (connected == IKS_NET_NOCONN) { 02289 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 02290 return IKS_HOOK; 02291 } else if (connected == IKS_NET_NODNS) { 02292 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server)); 02293 return IKS_HOOK; 02294 } 02295 02296 return IKS_OK; 02297 }
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 593 of file res_jabber.c.
References aji_is_secure(), ast_select(), len(), and aji_client::p.
Referenced by aji_recv().
00594 { 00595 int sock; 00596 fd_set fds; 00597 struct timeval tv, *tvptr = NULL; 00598 int len, res; 00599 00600 #ifdef HAVE_OPENSSL 00601 if (aji_is_secure(client)) { 00602 sock = SSL_get_fd(client->ssl_session); 00603 if (sock < 0) 00604 return -1; 00605 } else 00606 #endif /* HAVE_OPENSSL */ 00607 sock = iks_fd(client->p); 00608 00609 memset(&tv, 0, sizeof(struct timeval)); 00610 FD_ZERO(&fds); 00611 FD_SET(sock, &fds); 00612 tv.tv_sec = timeout; 00613 00614 /* NULL value for tvptr makes ast_select wait indefinitely */ 00615 tvptr = (timeout != -1) ? &tv : NULL; 00616 00617 /* ast_select emulates linux behaviour in terms of timeout handling */ 00618 res = ast_select(sock + 1, &fds, NULL, NULL, tvptr); 00619 if (res > 0) { 00620 #ifdef HAVE_OPENSSL 00621 if (aji_is_secure(client)) { 00622 len = SSL_read(client->ssl_session, buffer, buf_len); 00623 } else 00624 #endif /* HAVE_OPENSSL */ 00625 len = recv(sock, buffer, buf_len, 0); 00626 00627 if (len > 0) { 00628 return len; 00629 } else if (len <= 0) { 00630 return -1; 00631 } 00632 } 00633 return res; 00634 }
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 2879 of file res_jabber.c.
References AJI_AUTOPRUNE, AJI_AUTOREGISTER, ast_category_browse(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, debug, globalflags, JABBER_CONFIG, LOG_WARNING, and var.
Referenced by aji_reload().
02880 { 02881 char *cat = NULL; 02882 int debug = 1; 02883 struct ast_config *cfg = NULL; 02884 struct ast_variable *var = NULL; 02885 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02886 02887 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 02888 return -1; 02889 02890 /* Reset flags to default value */ 02891 ast_set_flag(&globalflags, AJI_AUTOREGISTER); 02892 02893 if (!cfg) { 02894 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 02895 return 0; 02896 } 02897 02898 cat = ast_category_browse(cfg, NULL); 02899 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 02900 if (!strcasecmp(var->name, "debug")) { 02901 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 02902 } else if (!strcasecmp(var->name, "autoprune")) { 02903 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 02904 } else if (!strcasecmp(var->name, "autoregister")) { 02905 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 02906 } 02907 } 02908 02909 while (cat) { 02910 if (strcasecmp(cat, "general")) { 02911 var = ast_variable_browse(cfg, cat); 02912 aji_create_client(cat, var, debug); 02913 } 02914 cat = ast_category_browse(cfg, cat); 02915 } 02916 ast_config_destroy(cfg); /* or leak memory */ 02917 return 1; 02918 }
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 787 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().
00788 { 00789 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00790 00791 if (!ast_strlen_zero(xmpp)) 00792 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 00793 00794 if (client->debug) { 00795 if (is_incoming) 00796 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 00797 else { 00798 if( strlen(xmpp) == 1) { 00799 if(option_debug > 2 && xmpp[0] == ' ') { 00800 ast_verbose("\nJABBER: Keep alive packet\n"); 00801 } 00802 } else 00803 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 00804 } 00805 00806 } 00807 ASTOBJ_UNREF(client, aji_client_destroy); 00808 }
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 2070 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.
02071 { 02072 int res = 0; 02073 iks *removeiq = iks_new("iq"); 02074 iks *removequery = iks_new("query"); 02075 iks *removeitem = iks_new("item"); 02076 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02077 if (!client || !removeiq || !removequery || !removeitem || !send) { 02078 ast_log(LOG_ERROR, "Out of memory.\n"); 02079 goto safeout; 02080 } 02081 02082 iks_insert_node(removeiq, removequery); 02083 iks_insert_node(removequery, removeitem); 02084 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02085 ASTOBJ_RDLOCK(iterator); 02086 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02087 * be called at the same time */ 02088 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02089 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02090 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02091 " so I am no longer subscribing to your presence.\n")); 02092 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02093 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02094 " your access to my presence.\n")); 02095 iks_insert_attrib(removeiq, "from", client->jid->full); 02096 iks_insert_attrib(removeiq, "type", "set"); 02097 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02098 iks_insert_attrib(removeitem, "jid", iterator->name); 02099 iks_insert_attrib(removeitem, "subscription", "remove"); 02100 res = ast_aji_send(client, removeiq); 02101 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02102 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02103 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02104 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02105 } 02106 ASTOBJ_UNLOCK(iterator); 02107 }); 02108 02109 safeout: 02110 iks_delete(removeiq); 02111 iks_delete(removequery); 02112 iks_delete(removeitem); 02113 iks_delete(send); 02114 02115 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); 02116 }
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 2207 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().
02208 { 02209 int res = 0; 02210 02211 if (client->state) 02212 client->state = AJI_DISCONNECTED; 02213 client->timeout=50; 02214 if (client->p) 02215 iks_parser_reset(client->p); 02216 if (client->authorized) 02217 client->authorized = 0; 02218 02219 res = aji_initialize(client); 02220 02221 return res; 02222 }
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 645 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().
00646 { 00647 int len, ret; 00648 char buf[NET_IO_BUF_SIZE - 1]; 00649 char newbuf[NET_IO_BUF_SIZE - 1]; 00650 int pos = 0; 00651 int newbufpos = 0; 00652 unsigned char c; 00653 00654 memset(buf, 0, sizeof(buf)); 00655 memset(newbuf, 0, sizeof(newbuf)); 00656 00657 while (1) { 00658 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 00659 if (len < 0) return IKS_NET_RWERR; 00660 if (len == 0) return IKS_NET_EXPIRED; 00661 buf[len] = '\0'; 00662 00663 /* our iksemel parser won't work as expected if we feed 00664 it with XML packets that contain multiple whitespace 00665 characters between tags */ 00666 while (pos < len) { 00667 c = buf[pos]; 00668 /* if we stumble on the ending tag character, 00669 we skip any whitespace that follows it*/ 00670 if (c == '>') { 00671 while (isspace(buf[pos+1])) { 00672 pos++; 00673 } 00674 } 00675 newbuf[newbufpos] = c; 00676 newbufpos ++; 00677 pos++; 00678 } 00679 pos = 0; 00680 newbufpos = 0; 00681 00682 /* Log the message here, because iksemel's logHook is 00683 unaccessible */ 00684 aji_log_hook(client, buf, len, 1); 00685 00686 /* let iksemel deal with the string length, 00687 and reset our buffer */ 00688 ret = iks_parse(client->p, newbuf, 0, 0); 00689 memset(newbuf, 0, sizeof(newbuf)); 00690 00691 switch (ret) { 00692 case IKS_NOMEM: 00693 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 00694 break; 00695 case IKS_BADXML: 00696 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 00697 break; 00698 case IKS_HOOK: 00699 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 00700 break; 00701 } 00702 if (ret != IKS_OK) { 00703 return ret; 00704 } 00705 ast_debug(3, "XML parsing successful\n"); 00706 } 00707 return IKS_OK; 00708 }
static void * aji_recv_loop | ( | void * | data | ) | [static] |
receive message loop.
data | void |
Definition at line 1909 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().
01910 { 01911 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01912 int res = IKS_HOOK; 01913 01914 while(res != IKS_OK) { 01915 ast_debug(3, "JABBER: Connecting.\n"); 01916 res = aji_reconnect(client); 01917 sleep(4); 01918 } 01919 01920 do { 01921 if (res == IKS_NET_RWERR || client->timeout == 0) { 01922 while(res != IKS_OK) { 01923 ast_debug(3, "JABBER: reconnecting.\n"); 01924 res = aji_reconnect(client); 01925 sleep(4); 01926 } 01927 } 01928 01929 res = aji_recv(client, 1); 01930 01931 if (client->state == AJI_DISCONNECTING) { 01932 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 01933 pthread_exit(NULL); 01934 } 01935 01936 /* Decrease timeout if no data received */ 01937 if (res == IKS_NET_EXPIRED) 01938 client->timeout--; 01939 01940 if (res == IKS_HOOK) 01941 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 01942 else if (res == IKS_NET_TLSFAIL) 01943 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 01944 else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 01945 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 01946 if(res == IKS_OK) 01947 client->timeout = 50; 01948 else 01949 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 01950 } else if (res == IKS_NET_RWERR) 01951 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 01952 } while (client); 01953 ASTOBJ_UNREF(client, aji_client_destroy); 01954 return 0; 01955 }
static int aji_register_approve_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Unknown.
data | void | |
pak | ikspak |
Definition at line 1068 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().
01069 { 01070 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01071 iks *iq = NULL, *presence = NULL, *x = NULL; 01072 01073 iq = iks_new("iq"); 01074 presence = iks_new("presence"); 01075 x = iks_new("x"); 01076 if (client && iq && presence && x) { 01077 if (!iks_find(pak->query, "remove")) { 01078 iks_insert_attrib(iq, "from", client->jid->full); 01079 iks_insert_attrib(iq, "to", pak->from->full); 01080 iks_insert_attrib(iq, "id", pak->id); 01081 iks_insert_attrib(iq, "type", "result"); 01082 ast_aji_send(client, iq); 01083 01084 iks_insert_attrib(presence, "from", client->jid->full); 01085 iks_insert_attrib(presence, "to", pak->from->partial); 01086 iks_insert_attrib(presence, "id", client->mid); 01087 ast_aji_increment_mid(client->mid); 01088 iks_insert_attrib(presence, "type", "subscribe"); 01089 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01090 iks_insert_node(presence, x); 01091 ast_aji_send(client, presence); 01092 } 01093 } else { 01094 ast_log(LOG_ERROR, "Out of memory.\n"); 01095 } 01096 01097 01098 iks_delete(iq); 01099 iks_delete(presence); 01100 iks_delete(x); 01101 01102 ASTOBJ_UNREF(client, aji_client_destroy); 01103 return IKS_FILTER_EAT; 01104 }
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 1111 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().
01112 { 01113 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01114 struct aji_buddy *buddy = NULL; 01115 char *node = NULL; 01116 iks *iq = NULL, *query = NULL; 01117 01118 client = (struct aji_client *) data; 01119 01120 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01121 if (!buddy) { 01122 iks *error = NULL, *notacceptable = NULL; 01123 01124 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01125 iq = iks_new("iq"); 01126 query = iks_new("query"); 01127 error = iks_new("error"); 01128 notacceptable = iks_new("not-acceptable"); 01129 if(iq && query && error && notacceptable) { 01130 iks_insert_attrib(iq, "type", "error"); 01131 iks_insert_attrib(iq, "from", client->user); 01132 iks_insert_attrib(iq, "to", pak->from->full); 01133 iks_insert_attrib(iq, "id", pak->id); 01134 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01135 iks_insert_attrib(error, "code" , "406"); 01136 iks_insert_attrib(error, "type", "modify"); 01137 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01138 iks_insert_node(iq, query); 01139 iks_insert_node(iq, error); 01140 iks_insert_node(error, notacceptable); 01141 ast_aji_send(client, iq); 01142 } else { 01143 ast_log(LOG_ERROR, "Out of memory.\n"); 01144 } 01145 01146 iks_delete(error); 01147 iks_delete(notacceptable); 01148 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01149 iks *instructions = NULL; 01150 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01151 iq = iks_new("iq"); 01152 query = iks_new("query"); 01153 instructions = iks_new("instructions"); 01154 if (iq && query && instructions && client) { 01155 iks_insert_attrib(iq, "from", client->user); 01156 iks_insert_attrib(iq, "to", pak->from->full); 01157 iks_insert_attrib(iq, "id", pak->id); 01158 iks_insert_attrib(iq, "type", "result"); 01159 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01160 iks_insert_cdata(instructions, explain, 0); 01161 iks_insert_node(iq, query); 01162 iks_insert_node(query, instructions); 01163 ast_aji_send(client, iq); 01164 } else { 01165 ast_log(LOG_ERROR, "Out of memory.\n"); 01166 } 01167 01168 iks_delete(instructions); 01169 } 01170 iks_delete(iq); 01171 iks_delete(query); 01172 ASTOBJ_UNREF(client, aji_client_destroy); 01173 return IKS_FILTER_EAT; 01174 }
static int aji_reload | ( | int | reload | ) | [static] |
Reload the jabber module.
Definition at line 3007 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().
03008 { 03009 int res; 03010 03011 ASTOBJ_CONTAINER_MARKALL(&clients); 03012 if (!(res = aji_load_config(reload))) { 03013 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 03014 return 0; 03015 } else if (res == -1) 03016 return 1; 03017 03018 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); 03019 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03020 ASTOBJ_RDLOCK(iterator); 03021 if(iterator->state == AJI_DISCONNECTED) { 03022 if (!iterator->thread) 03023 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 03024 } else if (iterator->state == AJI_CONNECTING) 03025 aji_get_roster(iterator); 03026 ASTOBJ_UNLOCK(iterator); 03027 }); 03028 03029 return 1; 03030 }
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|reciever|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 716 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().
00717 { 00718 char *msg; 00719 int len, err; 00720 00721 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 00722 msg = iks_malloc(len); 00723 if (!msg) 00724 return IKS_NOMEM; 00725 sprintf(msg, "<?xml version='1.0'?>" 00726 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 00727 "%s' to='%s' version='1.0'>", client->name_space, to); 00728 err = aji_send_raw(client, msg); 00729 iks_free(msg); 00730 if (err != IKS_OK) 00731 return err; 00732 00733 return IKS_OK; 00734 }
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 755 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().
00756 { 00757 int ret; 00758 #ifdef HAVE_OPENSSL 00759 int len = strlen(xmlstr); 00760 00761 if (aji_is_secure(client)) { 00762 ret = SSL_write(client->ssl_session, xmlstr, len); 00763 if (ret) { 00764 /* Log the message here, because iksemel's logHook is 00765 unaccessible */ 00766 aji_log_hook(client, xmlstr, len, 0); 00767 return IKS_OK; 00768 } 00769 } 00770 #endif 00771 /* If needed, data will be sent unencrypted, and logHook will 00772 be called inside iks_send_raw */ 00773 ret = iks_send_raw(client->p, xmlstr); 00774 if (ret != IKS_OK) 00775 return ret; 00776 00777 return IKS_OK; 00778 }
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 2332 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().
02333 { 02334 int res = 0; 02335 iks *presence = iks_make_pres(level, desc); 02336 iks *cnode = iks_new("c"); 02337 iks *priority = iks_new("priority"); 02338 char priorityS[10]; 02339 02340 if (presence && cnode && client && priority) { 02341 if(to) 02342 iks_insert_attrib(presence, "to", to); 02343 if(from) 02344 iks_insert_attrib(presence, "from", from); 02345 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 02346 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 02347 iks_insert_node(presence, priority); 02348 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 02349 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 02350 iks_insert_attrib(cnode, "ext", "voice-v1"); 02351 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 02352 iks_insert_node(presence, cnode); 02353 res = ast_aji_send(client, presence); 02354 } else 02355 ast_log(LOG_ERROR, "Out of memory.\n"); 02356 02357 iks_delete(cnode); 02358 iks_delete(presence); 02359 iks_delete(priority); 02360 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show buddy lists.
Definition at line 2513 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.
02514 { 02515 struct aji_resource *resource; 02516 struct aji_client *client; 02517 02518 switch (cmd) { 02519 case CLI_INIT: 02520 e->command = "jabber show buddies"; 02521 e->usage = 02522 "Usage: jabber show buddies\n" 02523 " Shows buddy lists of our clients\n"; 02524 return NULL; 02525 case CLI_GENERATE: 02526 return NULL; 02527 } 02528 02529 ast_cli(a->fd, "Jabber buddy lists\n"); 02530 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02531 ast_cli(a->fd,"Client: %s\n", iterator->user); 02532 client = iterator; 02533 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02534 ASTOBJ_RDLOCK(iterator); 02535 ast_cli(a->fd,"\tBuddy:\t%s\n", iterator->name); 02536 if (!iterator->resources) 02537 ast_cli(a->fd,"\t\tResource: None\n"); 02538 for (resource = iterator->resources; resource; resource = resource->next) { 02539 ast_cli(a->fd,"\t\tResource: %s\n", resource->resource); 02540 if(resource->cap) { 02541 ast_cli(a->fd,"\t\t\tnode: %s\n", resource->cap->parent->node); 02542 ast_cli(a->fd,"\t\t\tversion: %s\n", resource->cap->version); 02543 ast_cli(a->fd,"\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 02544 } 02545 ast_cli(a->fd,"\t\tStatus: %d\n", resource->status); 02546 ast_cli(a->fd,"\t\tPriority: %d\n", resource->priority); 02547 } 02548 ASTOBJ_UNLOCK(iterator); 02549 }); 02550 iterator = client; 02551 }); 02552 return CLI_SUCCESS; 02553 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show client status.
Definition at line 2468 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.
02469 { 02470 char *status; 02471 int count = 0; 02472 02473 switch (cmd) { 02474 case CLI_INIT: 02475 e->command = "jabber show connected"; 02476 e->usage = 02477 "Usage: jabber show connected\n" 02478 " Shows state of clients and components\n"; 02479 return NULL; 02480 case CLI_GENERATE: 02481 return NULL; 02482 } 02483 02484 ast_cli(a->fd, "Jabber Users and their status:\n"); 02485 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02486 ASTOBJ_RDLOCK(iterator); 02487 count++; 02488 switch (iterator->state) { 02489 case AJI_DISCONNECTED: 02490 status = "Disconnected"; 02491 break; 02492 case AJI_CONNECTING: 02493 status = "Connecting"; 02494 break; 02495 case AJI_CONNECTED: 02496 status = "Connected"; 02497 break; 02498 default: 02499 status = "Unknown"; 02500 } 02501 ast_cli(a->fd, " User: %s - %s\n", iterator->user, status); 02502 ASTOBJ_UNLOCK(iterator); 02503 }); 02504 ast_cli(a->fd, "----\n"); 02505 ast_cli(a->fd, " Number of users: %d\n", count); 02506 return CLI_SUCCESS; 02507 }
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 819 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().
00820 { 00821 iks *x = NULL; 00822 int len; 00823 char *s; 00824 char *base64; 00825 00826 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 00827 iks_start_sasl is an iksemel API function and relies on GnuTLS, 00828 whereas we use OpenSSL */ 00829 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 00830 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 00831 if (!(type & IKS_STREAM_SASL_PLAIN)) { 00832 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 00833 return IKS_NET_NOTSUPP; 00834 } 00835 00836 x = iks_new("auth"); 00837 if (!x) { 00838 ast_log(LOG_ERROR, "Out of memory.\n"); 00839 return IKS_NET_NOTSUPP; 00840 } 00841 00842 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 00843 len = strlen(username) + strlen(pass) + 3; 00844 s = alloca(len); 00845 base64 = alloca((len + 2) * 4 / 3); 00846 iks_insert_attrib(x, "mechanism", "PLAIN"); 00847 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 00848 00849 /* exclude the NULL training byte from the base64 encoding operation 00850 as some XMPP servers will refuse it. 00851 The format for authentication is [authzid]\0authcid\0password 00852 not [authzid]\0authcid\0password\0 */ 00853 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 00854 iks_insert_cdata(x, base64, 0); 00855 ast_aji_send(client, x); 00856 iks_delete(x); 00857 00858 return IKS_OK; 00859 }
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 2559 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.
02560 { 02561 struct aji_client *client; 02562 struct aji_resource *resource; 02563 const char *name = "asterisk"; 02564 struct aji_message *tmp; 02565 02566 switch (cmd) { 02567 case CLI_INIT: 02568 e->command = "jabber test"; 02569 e->usage = 02570 "Usage: jabber test [client]\n" 02571 " Sends test message for debugging purposes. A specific client\n" 02572 " as configured in jabber.conf can be optionally specified.\n"; 02573 return NULL; 02574 case CLI_GENERATE: 02575 return NULL; 02576 } 02577 02578 if (a->argc > 3) 02579 return CLI_SHOWUSAGE; 02580 else if (a->argc == 3) 02581 name = a->argv[2]; 02582 02583 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 02584 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 02585 return CLI_FAILURE; 02586 } 02587 02588 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 02589 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 02590 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02591 ASTOBJ_RDLOCK(iterator); 02592 ast_verbose("User: %s\n", iterator->name); 02593 for (resource = iterator->resources; resource; resource = resource->next) { 02594 ast_verbose("Resource: %s\n", resource->resource); 02595 if(resource->cap) { 02596 ast_verbose(" client: %s\n", resource->cap->parent->node); 02597 ast_verbose(" version: %s\n", resource->cap->version); 02598 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 02599 } 02600 ast_verbose(" Priority: %d\n", resource->priority); 02601 ast_verbose(" Status: %d\n", resource->status); 02602 ast_verbose(" Message: %s\n", S_OR(resource->description,"")); 02603 } 02604 ASTOBJ_UNLOCK(iterator); 02605 }); 02606 ast_verbose("\nOooh a working message stack!\n"); 02607 AST_LIST_LOCK(&client->messages); 02608 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 02609 ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 02610 } 02611 AST_LIST_UNLOCK(&client->messages); 02612 ASTOBJ_UNREF(client, aji_client_destroy); 02613 02614 return CLI_SUCCESS; 02615 }
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 /* Load encryption, hashing algorithms and error strings */ 00545 SSL_library_init(); 00546 SSL_load_error_strings(); 00547 00548 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 00549 client->ssl_method = SSLv3_method(); 00550 client->ssl_context = SSL_CTX_new(client->ssl_method); 00551 if (!client->ssl_context) 00552 return IKS_NET_TLSFAIL; 00553 00554 /* Create new SSL session */ 00555 client->ssl_session = SSL_new(client->ssl_context); 00556 if (!client->ssl_session) 00557 return IKS_NET_TLSFAIL; 00558 00559 /* Enforce TLS on our XMPP connection */ 00560 sock = iks_fd(client->p); 00561 ret = SSL_set_fd(client->ssl_session, sock); 00562 if (!ret) 00563 return IKS_NET_TLSFAIL; 00564 00565 /* Perform SSL handshake */ 00566 ret = SSL_connect(client->ssl_session); 00567 if (!ret) 00568 return IKS_NET_TLSFAIL; 00569 00570 client->stream_flags &= (~TRY_SECURE); 00571 client->stream_flags |= SECURE; 00572 00573 /* Sent over the established TLS connection */ 00574 ret = aji_send_header(client, client->jid->server); 00575 if (ret != IKS_OK) 00576 return IKS_NET_TLSFAIL; 00577 00578 ast_debug(1, "TLS started with server\n"); 00579 00580 return IKS_OK; 00581 }
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 1818 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01819 { 01820 int res = 0; 01821 iks *iq = NULL; 01822 iq = iks_new("iq"); 01823 01824 if (iq && client) { 01825 iks_insert_attrib(iq, "type", "get"); 01826 iks_insert_attrib(iq, "to", server); 01827 iks_insert_attrib(iq, "id", client->mid); 01828 ast_aji_increment_mid(client->mid); 01829 ast_aji_send(client, iq); 01830 } else 01831 ast_log(LOG_ERROR, "Out of memory.\n"); 01832 01833 iks_delete(iq); 01834 01835 return res; 01836 }
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 2304 of file res_jabber.c.
References aji_client_destroy(), ast_verb, ASTOBJ_UNREF, and aji_client::p.
Referenced by unload_module().
02305 { 02306 if (client) { 02307 ast_verb(4, "JABBER: Disconnecting\n"); 02308 #ifdef HAVE_OPENSSL 02309 if (client->stream_flags & SECURE) { 02310 SSL_shutdown(client->ssl_session); 02311 SSL_CTX_free(client->ssl_context); 02312 SSL_free(client->ssl_session); 02313 } 02314 #endif 02315 iks_disconnect(client->p); 02316 iks_parser_delete(client->p); 02317 ASTOBJ_UNREF(client, aji_client_destroy); 02318 } 02319 02320 return 1; 02321 }
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 2926 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().
02927 { 02928 struct aji_client *client = NULL; 02929 char *aux = NULL; 02930 02931 client = ASTOBJ_CONTAINER_FIND(&clients, name); 02932 if (!client && strchr(name, '@')) { 02933 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02934 aux = ast_strdupa(iterator->user); 02935 if (strchr(aux, '/')) { 02936 /* strip resource for comparison */ 02937 aux = strsep(&aux, "/"); 02938 } 02939 if (!strncasecmp(aux, name, strlen(aux))) { 02940 client = iterator; 02941 } 02942 }); 02943 } 02944 02945 return client; 02946 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) |
Definition at line 2948 of file res_jabber.c.
References clients.
02949 { 02950 return &clients; 02951 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 1962 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().
01963 { 01964 int i = 0; 01965 01966 for (i = strlen(mid) - 1; i >= 0; i--) { 01967 if (mid[i] != 'z') { 01968 mid[i] = mid[i] + 1; 01969 i = 0; 01970 } else 01971 mid[i] = 'a'; 01972 } 01973 }
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 1875 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01876 { 01877 int res = 0; 01878 iks *invite, *body, *namespace; 01879 01880 invite = iks_new("message"); 01881 body = iks_new("body"); 01882 namespace = iks_new("x"); 01883 if (client && invite && body && namespace) { 01884 iks_insert_attrib(invite, "to", user); 01885 iks_insert_attrib(invite, "id", client->mid); 01886 ast_aji_increment_mid(client->mid); 01887 iks_insert_cdata(body, message, 0); 01888 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 01889 iks_insert_attrib(namespace, "jid", room); 01890 iks_insert_node(invite, body); 01891 iks_insert_node(invite, namespace); 01892 res = ast_aji_send(client, invite); 01893 } else 01894 ast_log(LOG_ERROR, "Out of memory.\n"); 01895 01896 iks_delete(body); 01897 iks_delete(namespace); 01898 iks_delete(invite); 01899 01900 return res; 01901 }
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 1844 of file res_jabber.c.
References ast_aji_send(), ast_log(), and LOG_ERROR.
01845 { 01846 int res = 0; 01847 iks *presence = NULL, *priority = NULL; 01848 presence = iks_new("presence"); 01849 priority = iks_new("priority"); 01850 if (presence && priority && client) { 01851 iks_insert_cdata(priority, "0", 1); 01852 iks_insert_attrib(presence, "to", room); 01853 iks_insert_node(presence, priority); 01854 res = ast_aji_send(client, presence); 01855 iks_insert_cdata(priority, "5", 1); 01856 iks_insert_attrib(presence, "to", room); 01857 res = ast_aji_send(client, presence); 01858 } else 01859 ast_log(LOG_ERROR, "Out of memory.\n"); 01860 01861 iks_delete(presence); 01862 iks_delete(priority); 01863 01864 return res; 01865 }
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 742 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().
00743 { 00744 return aji_send_raw(client, iks_string(iks_stack(x), x)); 00745 }
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 1791 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().
01792 { 01793 int res = 0; 01794 iks *message_packet = NULL; 01795 if (client->state == AJI_CONNECTED) { 01796 message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message); 01797 if (message_packet) { 01798 iks_insert_attrib(message_packet, "from", client->jid->full); 01799 res = ast_aji_send(client, message_packet); 01800 } else { 01801 ast_log(LOG_ERROR, "Out of memory.\n"); 01802 } 01803 01804 iks_delete(message_packet); 01805 } else 01806 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 01807 return 1; 01808 }
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 3057 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.
03058 { 03059 ASTOBJ_CONTAINER_INIT(&clients); 03060 if(!aji_reload(0)) 03061 return AST_MODULE_LOAD_DECLINE; 03062 ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, 03063 "Sends a message to a Jabber Client", mandescr_jabber_send); 03064 ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip); 03065 ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip); 03066 ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); 03067 ast_custom_function_register(&jabberstatus_function); 03068 03069 return 0; 03070 }
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 2966 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().
02967 { 02968 struct aji_client *client = NULL; 02969 const char *id = astman_get_header(m,"ActionID"); 02970 const char *jabber = astman_get_header(m,"Jabber"); 02971 const char *screenname = astman_get_header(m,"ScreenName"); 02972 const char *message = astman_get_header(m,"Message"); 02973 02974 if (ast_strlen_zero(jabber)) { 02975 astman_send_error(s, m, "No transport specified"); 02976 return 0; 02977 } 02978 if (ast_strlen_zero(screenname)) { 02979 astman_send_error(s, m, "No ScreenName specified"); 02980 return 0; 02981 } 02982 if (ast_strlen_zero(message)) { 02983 astman_send_error(s, m, "No Message specified"); 02984 return 0; 02985 } 02986 02987 astman_send_ack(s, m, "Attempting to send Jabber Message"); 02988 client = ast_aji_get_client(jabber); 02989 if (!client) { 02990 astman_send_error(s, m, "Could not find Sender"); 02991 return 0; 02992 } 02993 if (strchr(screenname, '@') && message) { 02994 ast_aji_send_chat(client, screenname, message); 02995 astman_append(s, "Response: Success\r\n"); 02996 } else { 02997 astman_append(s, "Response: Error\r\n"); 02998 } 02999 if (!ast_strlen_zero(id)) { 03000 astman_append(s, "ActionID: %s\r\n",id); 03001 } 03002 astman_append(s, "\r\n"); 03003 return 0; 03004 }
static int reload | ( | void | ) | [static] |
Wrapper for aji_reload.
Definition at line 3073 of file res_jabber.c.
References aji_reload().
03074 { 03075 aji_reload(1); 03076 return 0; 03077 }
static int unload_module | ( | void | ) | [static] |
Unload the jabber module.
Definition at line 3033 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.
03034 { 03035 03036 ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); 03037 ast_unregister_application(app_ajisend); 03038 ast_unregister_application(app_ajistatus); 03039 ast_manager_unregister("JabberSend"); 03040 ast_custom_function_unregister(&jabberstatus_function); 03041 03042 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03043 ASTOBJ_RDLOCK(iterator); 03044 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 03045 iterator->state = AJI_DISCONNECTING; 03046 ast_aji_disconnect(iterator); 03047 pthread_join(iterator->thread, NULL); 03048 ASTOBJ_UNLOCK(iterator); 03049 }); 03050 03051 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); 03052 ASTOBJ_CONTAINER_DESTROY(&clients); 03053 return 0; 03054 }
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3083 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.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3083 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_AUTOREGISTER } [static] |
struct ast_custom_function jabberstatus_function [static] |
char mandescr_jabber_send[] [static] |