#include "asterisk.h"
#include <ctype.h>
#include <iksemel.h>
#include "asterisk/channel.h"
#include "asterisk/jabber.h"
#include "asterisk/file.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/astobj.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
Go to the source code of this file.
Defines | |
#define | FALSE 0 |
#define | JABBER_CONFIG "jabber.conf" |
#define | TRUE 1 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | acf_jabberstatus_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
static int | aji_act_hook (void *data, int type, iks *node) |
The action hook parses the inbound packets, constantly running. | |
static void | aji_buddy_destroy (struct aji_buddy *obj) |
Deletes the aji_buddy data structure. | |
static int | aji_client_connect (void *data, ikspak *pak) |
connects as a client to jabber server. | |
static void | aji_client_destroy (struct aji_client *obj) |
Deletes the aji_client data structure. | |
static int | aji_client_info_handler (void *data, ikspak *pak) |
Handle add extra info. | |
static int | aji_create_buddy (char *label, struct aji_client *client) |
creates buddy. | |
static int | aji_create_client (char *label, struct ast_variable *var, int debug) |
creates aji_client structure. | |
static int | aji_dinfo_handler (void *data, ikspak *pak) |
Handler of the return info packet. | |
static int | aji_ditems_handler (void *data, ikspak *pak) |
Handles stuff. | |
static char * | aji_do_debug_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Turn on/off console debugging (deprecated, use aji_do_set_debug). | |
static char * | aji_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Reload jabber module. | |
static char * | aji_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Turn on/off console debugging. | |
static int | aji_filter_roster (void *data, ikspak *pak) |
filters the roster packet we get back from server. | |
static struct aji_resource * | aji_find_resource (struct aji_buddy *buddy, char *name) |
Find the aji_resource we want. | |
static struct aji_version * | aji_find_version (char *node, char *version, ikspak *pak) |
Find version in XML stream and populate our capabilities list. | |
static int | aji_get_roster (struct aji_client *client) |
Get the roster of jabber users. | |
static void | aji_handle_iq (struct aji_client *client, iks *node) |
Handles. | |
static void | aji_handle_message (struct aji_client *client, ikspak *pak) |
Handles presence packets. | |
static void | aji_handle_presence (struct aji_client *client, ikspak *pak) |
Check the presence info. | |
static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
handles subscription requests. | |
static int | aji_initialize (struct aji_client *client) |
prepares client for connect. | |
static int | aji_io_recv (struct aji_client *client, char *buffer, size_t buf_len, int timeout) |
Secured or unsecured IO socket receiving function. | |
static int | aji_is_secure (struct aji_client *client) |
Tests whether the connection is secured or not. | |
static int | aji_load_config (int reload) |
static void | aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming) |
the debug loop. | |
static void | aji_pruneregister (struct aji_client *client) |
goes through roster and prunes users not needed in list, or adds them accordingly. | |
static int | aji_reconnect (struct aji_client *client) |
reconnect to jabber server | |
static int | aji_recv (struct aji_client *client, int timeout) |
Tries to receive data from the Jabber server. | |
static void * | aji_recv_loop (void *data) |
receive message loop. | |
static int | aji_register_approve_handler (void *data, ikspak *pak) |
Unknown. | |
static int | aji_register_query_handler (void *data, ikspak *pak) |
register handler for incoming querys (IQ's) | |
static int | aji_reload (int reload) |
Reload the jabber module. | |
static int | aji_send_exec (struct ast_channel *chan, void *data) |
Dial plan function to send a message. | |
static int | aji_send_header (struct aji_client *client, const char *to) |
Sends XMPP header to the server. | |
static int | aji_send_raw (struct aji_client *client, const char *xmlstr) |
Sends an XML string over an XMPP connection. | |
static void | aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc) |
set presence of client. | |
static char * | aji_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Show buddy lists. | |
static char * | aji_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Show client status. | |
static int | aji_start_sasl (struct aji_client *client, enum ikssasltype type, char *username, char *pass) |
A wrapper function for iks_start_sasl. | |
static int | aji_start_tls (struct aji_client *client) |
Starts the TLS procedure. | |
static int | aji_status_exec (struct ast_channel *chan, void *data) |
Dial plan function status(). puts the status of watched user into a channel variable. | |
static char * | aji_test (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Send test message for debugging. | |
static int | aji_tls_handshake (struct aji_client *client) |
TLS handshake, OpenSSL initialization. | |
int | ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic) |
create a chatroom. | |
int | ast_aji_disconnect (struct aji_client *client) |
disconnect from jabber server. | |
aji_client * | ast_aji_get_client (const char *name) |
grab a aji_client structure by label name or JID (without the resource string) | |
aji_client_container * | ast_aji_get_clients (void) |
void | ast_aji_increment_mid (char *mid) |
increments the mid field for messages and other events. | |
int | ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message) |
invite to a chatroom. | |
int | ast_aji_join_chat (struct aji_client *client, char *room) |
join a chatroom. | |
int | ast_aji_send (struct aji_client *client, iks *x) |
Wraps raw sending. | |
int | ast_aji_send_chat (struct aji_client *client, const char *address, const char *message) |
sends messages. | |
static int | gtalk_yuck (iks *node) |
Jabber GTalk function. | |
static iks * | jabber_make_auth (iksid *id, const char *pass, const char *sid) |
Setup the authentication struct. | |
static int | load_module (void) |
Unload the jabber module. | |
static int | manager_jabber_send (struct mansession *s, const struct message *m) |
Send a Jabber Message via call from the Manager. | |
static int | reload (void) |
Wrapper for aji_reload. | |
static int | unload_module (void) |
Unload the jabber module. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
static struct ast_cli_entry | aji_cli [] |
static char * | ajisend_descrip |
static char * | ajisend_synopsis = "JabberSend(jabber,screenname,message)" |
static char * | ajistatus_descrip |
static char * | ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)" |
static char * | app_ajisend = "JabberSend" |
static char * | app_ajistatus = "JabberStatus" |
static struct ast_module_info * | ast_module_info = &__mod_info |
aji_capabilities * | capabilities = NULL |
static struct ast_cli_entry | cli_aji_do_debug_deprecated = { .handler = aji_do_debug_deprecated , .summary = "Enable/disable jabber debugging" ,__VA_ARGS__ } |
aji_client_container | clients |
static struct ast_flags | globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER } |
Global flags, initialized to default values. | |
static struct ast_custom_function | jabberstatus_function |
static char | mandescr_jabber_send [] |
References:
Dialplan applications need RETURN variable, like JABBERSENDSTATUS
Definition in file res_jabber.c.
#define FALSE 0 |
Definition at line 67 of file res_jabber.c.
#define JABBER_CONFIG "jabber.conf" |
Definition at line 64 of file res_jabber.c.
Referenced by aji_load_config().
#define TRUE 1 |
Definition at line 71 of file res_jabber.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 3072 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 3072 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 858 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().
00859 { 00860 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00861 ikspak *pak = NULL; 00862 iks *auth = NULL; 00863 int features = 0; 00864 00865 if(!node) { 00866 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 00867 ASTOBJ_UNREF(client, aji_client_destroy); 00868 return IKS_HOOK; 00869 } 00870 00871 if (client->state == AJI_DISCONNECTING) { 00872 ASTOBJ_UNREF(client, aji_client_destroy); 00873 return IKS_HOOK; 00874 } 00875 00876 pak = iks_packet(node); 00877 00878 if (!client->component) { /*client */ 00879 switch (type) { 00880 case IKS_NODE_START: 00881 if (client->usetls && !aji_is_secure(client)) { 00882 #ifndef HAVE_OPENSSL 00883 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"); 00884 ASTOBJ_UNREF(client, aji_client_destroy); 00885 return IKS_HOOK; 00886 #else 00887 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 00888 ast_log(LOG_ERROR, "Could not start TLS\n"); 00889 ASTOBJ_UNREF(client, aji_client_destroy); 00890 return IKS_HOOK; 00891 } 00892 #endif 00893 break; 00894 } 00895 if (!client->usesasl) { 00896 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); 00897 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 00898 if (auth) { 00899 iks_insert_attrib(auth, "id", client->mid); 00900 iks_insert_attrib(auth, "to", client->jid->server); 00901 ast_aji_increment_mid(client->mid); 00902 ast_aji_send(client, auth); 00903 iks_delete(auth); 00904 } else 00905 ast_log(LOG_ERROR, "Out of memory.\n"); 00906 } 00907 break; 00908 00909 case IKS_NODE_NORMAL: 00910 #ifdef HAVE_OPENSSL 00911 if (client->stream_flags & TRY_SECURE) { 00912 if (!strcmp("proceed", iks_name(node))) { 00913 return aji_tls_handshake(client); 00914 } 00915 } 00916 #endif 00917 if (!strcmp("stream:features", iks_name(node))) { 00918 features = iks_stream_features(node); 00919 if (client->usesasl) { 00920 if (client->usetls && !aji_is_secure(client)) 00921 break; 00922 if (client->authorized) { 00923 if (features & IKS_STREAM_BIND) { 00924 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); 00925 auth = iks_make_resource_bind(client->jid); 00926 if (auth) { 00927 iks_insert_attrib(auth, "id", client->mid); 00928 ast_aji_increment_mid(client->mid); 00929 ast_aji_send(client, auth); 00930 iks_delete(auth); 00931 } else { 00932 ast_log(LOG_ERROR, "Out of memory.\n"); 00933 break; 00934 } 00935 } 00936 if (features & IKS_STREAM_SESSION) { 00937 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); 00938 auth = iks_make_session(); 00939 if (auth) { 00940 iks_insert_attrib(auth, "id", "auth"); 00941 ast_aji_increment_mid(client->mid); 00942 ast_aji_send(client, auth); 00943 iks_delete(auth); 00944 } else { 00945 ast_log(LOG_ERROR, "Out of memory.\n"); 00946 } 00947 } 00948 } else { 00949 int ret; 00950 if (!client->jid->user) { 00951 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 00952 break; 00953 } 00954 00955 ret = aji_start_sasl(client, features, client->jid->user, client->password); 00956 if (ret != IKS_OK) { 00957 ASTOBJ_UNREF(client, aji_client_destroy); 00958 return IKS_HOOK; 00959 } 00960 break; 00961 } 00962 } 00963 } else if (!strcmp("failure", iks_name(node))) { 00964 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 00965 } else if (!strcmp("success", iks_name(node))) { 00966 client->authorized = 1; 00967 aji_send_header(client, client->jid->server); 00968 } 00969 break; 00970 case IKS_NODE_ERROR: 00971 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 00972 ASTOBJ_UNREF(client, aji_client_destroy); 00973 return IKS_HOOK; 00974 break; 00975 case IKS_NODE_STOP: 00976 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 00977 ASTOBJ_UNREF(client, aji_client_destroy); 00978 return IKS_HOOK; 00979 break; 00980 } 00981 } else if (client->state != AJI_CONNECTED && client->component) { 00982 switch (type) { 00983 case IKS_NODE_START: 00984 if (client->state == AJI_DISCONNECTED) { 00985 char secret[160], shasum[320], *handshake; 00986 00987 sprintf(secret, "%s%s", pak->id, client->password); 00988 ast_sha1_hash(shasum, secret); 00989 handshake = NULL; 00990 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 00991 aji_send_raw(client, handshake); 00992 ast_free(handshake); 00993 handshake = NULL; 00994 } 00995 client->state = AJI_CONNECTING; 00996 if(aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 00997 client->state = AJI_CONNECTED; 00998 else 00999 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01000 break; 01001 } 01002 break; 01003 01004 case IKS_NODE_NORMAL: 01005 break; 01006 01007 case IKS_NODE_ERROR: 01008 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01009 ASTOBJ_UNREF(client, aji_client_destroy); 01010 return IKS_HOOK; 01011 01012 case IKS_NODE_STOP: 01013 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01014 ASTOBJ_UNREF(client, aji_client_destroy); 01015 return IKS_HOOK; 01016 } 01017 } 01018 01019 switch (pak->type) { 01020 case IKS_PAK_NONE: 01021 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01022 break; 01023 case IKS_PAK_MESSAGE: 01024 aji_handle_message(client, pak); 01025 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01026 break; 01027 case IKS_PAK_PRESENCE: 01028 aji_handle_presence(client, pak); 01029 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01030 break; 01031 case IKS_PAK_S10N: 01032 aji_handle_subscribe(client, pak); 01033 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01034 break; 01035 case IKS_PAK_IQ: 01036 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01037 aji_handle_iq(client, node); 01038 break; 01039 default: 01040 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01041 break; 01042 } 01043 01044 iks_filter_packet(client->f, pak); 01045 01046 if (node) 01047 iks_delete(node); 01048 01049 ASTOBJ_UNREF(client, aji_client_destroy); 01050 return IKS_OK; 01051 }
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 2241 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().
02242 { 02243 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02244 int res = 0; 02245 02246 if (client) { 02247 if (client->state == AJI_DISCONNECTED) { 02248 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); 02249 client->state = AJI_CONNECTING; 02250 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 02251 iks_filter_remove_hook(client->f, aji_client_connect); 02252 if(!client->component) /*client*/ 02253 aji_get_roster(client); 02254 } 02255 } else 02256 ast_log(LOG_ERROR, "Out of memory.\n"); 02257 02258 ASTOBJ_UNREF(client, aji_client_destroy); 02259 return res; 02260 }
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 1267 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().
01268 { 01269 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01270 struct aji_resource *resource = NULL; 01271 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01272 01273 resource = aji_find_resource(buddy, pak->from->resource); 01274 if (pak->subtype == IKS_TYPE_RESULT) { 01275 if (!resource) { 01276 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 01277 ASTOBJ_UNREF(client, aji_client_destroy); 01278 return IKS_FILTER_EAT; 01279 } 01280 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01281 resource->cap->jingle = 1; 01282 } else 01283 resource->cap->jingle = 0; 01284 } else if (pak->subtype == IKS_TYPE_GET) { 01285 iks *iq, *disco, *ident, *google, *query; 01286 iq = iks_new("iq"); 01287 query = iks_new("query"); 01288 ident = iks_new("identity"); 01289 disco = iks_new("feature"); 01290 google = iks_new("feature"); 01291 if (iq && ident && disco && google) { 01292 iks_insert_attrib(iq, "from", client->jid->full); 01293 iks_insert_attrib(iq, "to", pak->from->full); 01294 iks_insert_attrib(iq, "type", "result"); 01295 iks_insert_attrib(iq, "id", pak->id); 01296 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01297 iks_insert_attrib(ident, "category", "client"); 01298 iks_insert_attrib(ident, "type", "pc"); 01299 iks_insert_attrib(ident, "name", "asterisk"); 01300 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 01301 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 01302 iks_insert_node(iq, query); 01303 iks_insert_node(query, ident); 01304 iks_insert_node(query, google); 01305 iks_insert_node(query, disco); 01306 ast_aji_send(client, iq); 01307 } else 01308 ast_log(LOG_ERROR, "Out of Memory.\n"); 01309 01310 iks_delete(iq); 01311 iks_delete(query); 01312 iks_delete(ident); 01313 iks_delete(google); 01314 iks_delete(disco); 01315 } else if (pak->subtype == IKS_TYPE_ERROR) { 01316 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 01317 } 01318 ASTOBJ_UNREF(client, aji_client_destroy); 01319 return IKS_FILTER_EAT; 01320 }
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 2842 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 2614 of file res_jabber.c.
References aji_act_hook(), AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_destroy(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_calloc, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, ast_free, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::f, aji_client::flags, aji_client::forcessl, globalflags, aji_client::jid, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, aji_client::name, aji_client::name_space, aji_client::p, aji_client::password, aji_client::port, aji_client::priority, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and var.
Referenced by aji_load_config().
02615 { 02616 char *resource; 02617 struct aji_client *client = NULL; 02618 int flag = 0; 02619 02620 client = ASTOBJ_CONTAINER_FIND(&clients,label); 02621 if (!client) { 02622 flag = 1; 02623 client = ast_calloc(1, sizeof(*client)); 02624 if (!client) { 02625 ast_log(LOG_ERROR, "Out of memory!\n"); 02626 return 0; 02627 } 02628 ASTOBJ_INIT(client); 02629 ASTOBJ_WRLOCK(client); 02630 ASTOBJ_CONTAINER_INIT(&client->buddies); 02631 } else { 02632 ASTOBJ_WRLOCK(client); 02633 ASTOBJ_UNMARK(client); 02634 } 02635 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 02636 ast_copy_string(client->name, label, sizeof(client->name)); 02637 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 02638 02639 /* Set default values for the client object */ 02640 client->debug = debug; 02641 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 02642 client->port = 5222; 02643 client->usetls = 1; 02644 client->usesasl = 1; 02645 client->forcessl = 0; 02646 client->keepalive = 1; 02647 client->timeout = 50; 02648 client->message_timeout = 100; 02649 AST_LIST_HEAD_INIT(&client->messages); 02650 client->component = 0; 02651 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 02652 client->priority = 0; 02653 client->status = IKS_SHOW_AVAILABLE; 02654 02655 if (flag) { 02656 client->authorized = 0; 02657 client->state = AJI_DISCONNECTED; 02658 } 02659 while (var) { 02660 if (!strcasecmp(var->name, "username")) 02661 ast_copy_string(client->user, var->value, sizeof(client->user)); 02662 else if (!strcasecmp(var->name, "serverhost")) 02663 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 02664 else if (!strcasecmp(var->name, "secret")) 02665 ast_copy_string(client->password, var->value, sizeof(client->password)); 02666 else if (!strcasecmp(var->name, "statusmessage")) 02667 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 02668 else if (!strcasecmp(var->name, "port")) 02669 client->port = atoi(var->value); 02670 else if (!strcasecmp(var->name, "timeout")) 02671 client->message_timeout = atoi(var->value); 02672 else if (!strcasecmp(var->name, "debug")) 02673 client->debug = (ast_false(var->value)) ? 0 : 1; 02674 else if (!strcasecmp(var->name, "type")) { 02675 if (!strcasecmp(var->value, "component")) 02676 client->component = 1; 02677 } else if (!strcasecmp(var->name, "usetls")) { 02678 client->usetls = (ast_false(var->value)) ? 0 : 1; 02679 } else if (!strcasecmp(var->name, "usesasl")) { 02680 client->usesasl = (ast_false(var->value)) ? 0 : 1; 02681 } else if (!strcasecmp(var->name, "forceoldssl")) 02682 client->forcessl = (ast_false(var->value)) ? 0 : 1; 02683 else if (!strcasecmp(var->name, "keepalive")) 02684 client->keepalive = (ast_false(var->value)) ? 0 : 1; 02685 else if (!strcasecmp(var->name, "autoprune")) 02686 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 02687 else if (!strcasecmp(var->name, "autoregister")) 02688 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 02689 else if (!strcasecmp(var->name, "buddy")) 02690 aji_create_buddy((char *)var->value, client); 02691 else if (!strcasecmp(var->name, "priority")) 02692 client->priority = atoi(var->value); 02693 else if (!strcasecmp(var->name, "status")) { 02694 if (!strcasecmp(var->value, "unavailable")) 02695 client->status = IKS_SHOW_UNAVAILABLE; 02696 else 02697 if (!strcasecmp(var->value, "available") 02698 || !strcasecmp(var->value, "online")) 02699 client->status = IKS_SHOW_AVAILABLE; 02700 else 02701 if (!strcasecmp(var->value, "chat") 02702 || !strcasecmp(var->value, "chatty")) 02703 client->status = IKS_SHOW_CHAT; 02704 else 02705 if (!strcasecmp(var->value, "away")) 02706 client->status = IKS_SHOW_AWAY; 02707 else 02708 if (!strcasecmp(var->value, "xa") 02709 || !strcasecmp(var->value, "xaway")) 02710 client->status = IKS_SHOW_XA; 02711 else 02712 if (!strcasecmp(var->value, "dnd")) 02713 client->status = IKS_SHOW_DND; 02714 else 02715 if (!strcasecmp(var->value, "invisible")) 02716 #ifdef IKS_SHOW_INVISIBLE 02717 client->status = IKS_SHOW_INVISIBLE; 02718 #else 02719 { 02720 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 02721 client->status = IKS_SHOW_DND; 02722 } 02723 #endif 02724 else 02725 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 02726 } 02727 /* no transport support in this version */ 02728 /* else if (!strcasecmp(var->name, "transport")) 02729 aji_create_transport(var->value, client); 02730 */ 02731 var = var->next; 02732 } 02733 if (!flag) { 02734 ASTOBJ_UNLOCK(client); 02735 ASTOBJ_UNREF(client, aji_client_destroy); 02736 return 1; 02737 } 02738 02739 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 02740 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 02741 if (!client->p) { 02742 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 02743 return 0; 02744 } 02745 client->stack = iks_stack_new(8192, 8192); 02746 if (!client->stack) { 02747 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 02748 return 0; 02749 } 02750 client->f = iks_filter_new(); 02751 if (!client->f) { 02752 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 02753 return 0; 02754 } 02755 if (!strchr(client->user, '/') && !client->component) { /*client */ 02756 resource = NULL; 02757 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02758 client->jid = iks_id_new(client->stack, resource); 02759 ast_free(resource); 02760 } 02761 } else 02762 client->jid = iks_id_new(client->stack, client->user); 02763 if (client->component) { 02764 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02765 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 02766 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); 02767 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); 02768 } else { 02769 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 02770 } 02771 if (!strchr(client->user, '/') && !client->component) { /*client */ 02772 resource = NULL; 02773 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 02774 client->jid = iks_id_new(client->stack, resource); 02775 ast_free(resource); 02776 } 02777 } else 02778 client->jid = iks_id_new(client->stack, client->user); 02779 iks_set_log_hook(client->p, aji_log_hook); 02780 ASTOBJ_UNLOCK(client); 02781 ASTOBJ_CONTAINER_LINK(&clients,client); 02782 return 1; 02783 }
static int aji_dinfo_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handler of the return info packet.
data | aji_client | |
pak | ikspak |
Definition at line 1327 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().
01328 { 01329 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01330 char *node = NULL; 01331 struct aji_resource *resource = NULL; 01332 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01333 01334 resource = aji_find_resource(buddy, pak->from->resource); 01335 if (pak->subtype == IKS_TYPE_ERROR) { 01336 ast_log(LOG_WARNING, "Recieved error from a client, turn on jabber debug!\n"); 01337 return IKS_FILTER_EAT; 01338 } 01339 if (pak->subtype == IKS_TYPE_RESULT) { 01340 if (!resource) { 01341 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); 01342 ASTOBJ_UNREF(client, aji_client_destroy); 01343 return IKS_FILTER_EAT; 01344 } 01345 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01346 resource->cap->jingle = 1; 01347 } else 01348 resource->cap->jingle = 0; 01349 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 01350 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 01351 01352 iq = iks_new("iq"); 01353 query = iks_new("query"); 01354 identity = iks_new("identity"); 01355 disco = iks_new("feature"); 01356 reg = iks_new("feature"); 01357 commands = iks_new("feature"); 01358 gateway = iks_new("feature"); 01359 version = iks_new("feature"); 01360 vcard = iks_new("feature"); 01361 search = iks_new("feature"); 01362 01363 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 01364 iks_insert_attrib(iq, "from", client->user); 01365 iks_insert_attrib(iq, "to", pak->from->full); 01366 iks_insert_attrib(iq, "id", pak->id); 01367 iks_insert_attrib(iq, "type", "result"); 01368 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01369 iks_insert_attrib(identity, "category", "gateway"); 01370 iks_insert_attrib(identity, "type", "pstn"); 01371 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 01372 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 01373 iks_insert_attrib(reg, "var", "jabber:iq:register"); 01374 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 01375 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 01376 iks_insert_attrib(version, "var", "jabber:iq:version"); 01377 iks_insert_attrib(vcard, "var", "vcard-temp"); 01378 iks_insert_attrib(search, "var", "jabber:iq:search"); 01379 01380 iks_insert_node(iq, query); 01381 iks_insert_node(query, identity); 01382 iks_insert_node(query, disco); 01383 iks_insert_node(query, reg); 01384 iks_insert_node(query, commands); 01385 iks_insert_node(query, gateway); 01386 iks_insert_node(query, version); 01387 iks_insert_node(query, vcard); 01388 iks_insert_node(query, search); 01389 ast_aji_send(client, iq); 01390 } else { 01391 ast_log(LOG_ERROR, "Out of memory.\n"); 01392 } 01393 01394 iks_delete(iq); 01395 iks_delete(query); 01396 iks_delete(identity); 01397 iks_delete(disco); 01398 iks_delete(reg); 01399 iks_delete(commands); 01400 iks_delete(gateway); 01401 iks_delete(version); 01402 iks_delete(vcard); 01403 iks_delete(search); 01404 01405 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 01406 iks *iq, *query, *confirm; 01407 iq = iks_new("iq"); 01408 query = iks_new("query"); 01409 confirm = iks_new("item"); 01410 01411 if (iq && query && confirm && client) { 01412 iks_insert_attrib(iq, "from", client->user); 01413 iks_insert_attrib(iq, "to", pak->from->full); 01414 iks_insert_attrib(iq, "id", pak->id); 01415 iks_insert_attrib(iq, "type", "result"); 01416 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01417 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01418 iks_insert_attrib(confirm, "node", "confirmaccount"); 01419 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01420 iks_insert_attrib(confirm, "jid", client->user); 01421 iks_insert_node(iq, query); 01422 iks_insert_node(query, confirm); 01423 ast_aji_send(client, iq); 01424 } else { 01425 ast_log(LOG_ERROR, "Out of memory.\n"); 01426 } 01427 01428 iks_delete(iq); 01429 iks_delete(query); 01430 iks_delete(confirm); 01431 01432 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 01433 iks *iq, *query, *feature; 01434 01435 iq = iks_new("iq"); 01436 query = iks_new("query"); 01437 feature = iks_new("feature"); 01438 01439 if (iq && query && feature && client) { 01440 iks_insert_attrib(iq, "from", client->user); 01441 iks_insert_attrib(iq, "to", pak->from->full); 01442 iks_insert_attrib(iq, "id", pak->id); 01443 iks_insert_attrib(iq, "type", "result"); 01444 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01445 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01446 iks_insert_node(iq, query); 01447 iks_insert_node(query, feature); 01448 ast_aji_send(client, iq); 01449 } else { 01450 ast_log(LOG_ERROR, "Out of memory.\n"); 01451 } 01452 01453 iks_delete(iq); 01454 iks_delete(query); 01455 iks_delete(feature); 01456 } 01457 01458 ASTOBJ_UNREF(client, aji_client_destroy); 01459 return IKS_FILTER_EAT; 01460 }
static int aji_ditems_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Handles stuff.
data | void | |
pak | ikspak |
Definition at line 1172 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().
01173 { 01174 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01175 char *node = NULL; 01176 01177 if (!(node = iks_find_attrib(pak->query, "node"))) { 01178 iks *iq = NULL, *query = NULL, *item = NULL; 01179 iq = iks_new("iq"); 01180 query = iks_new("query"); 01181 item = iks_new("item"); 01182 01183 if (iq && query && item) { 01184 iks_insert_attrib(iq, "from", client->user); 01185 iks_insert_attrib(iq, "to", pak->from->full); 01186 iks_insert_attrib(iq, "id", pak->id); 01187 iks_insert_attrib(iq, "type", "result"); 01188 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01189 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01190 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01191 iks_insert_attrib(item, "jid", client->user); 01192 01193 iks_insert_node(iq, query); 01194 iks_insert_node(query, item); 01195 ast_aji_send(client, iq); 01196 } else { 01197 ast_log(LOG_ERROR, "Out of memory.\n"); 01198 } 01199 01200 iks_delete(iq); 01201 iks_delete(query); 01202 iks_delete(item); 01203 01204 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01205 iks *iq, *query, *confirm; 01206 iq = iks_new("iq"); 01207 query = iks_new("query"); 01208 confirm = iks_new("item"); 01209 if (iq && query && confirm && client) { 01210 iks_insert_attrib(iq, "from", client->user); 01211 iks_insert_attrib(iq, "to", pak->from->full); 01212 iks_insert_attrib(iq, "id", pak->id); 01213 iks_insert_attrib(iq, "type", "result"); 01214 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01215 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01216 iks_insert_attrib(confirm, "node", "confirmaccount"); 01217 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01218 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01219 01220 iks_insert_node(iq, query); 01221 iks_insert_node(query, confirm); 01222 ast_aji_send(client, iq); 01223 } else { 01224 ast_log(LOG_ERROR, "Out of memory.\n"); 01225 } 01226 01227 iks_delete(iq); 01228 iks_delete(query); 01229 iks_delete(confirm); 01230 01231 } else if (!strcasecmp(node, "confirmaccount")) { 01232 iks *iq = NULL, *query = NULL, *feature = NULL; 01233 01234 iq = iks_new("iq"); 01235 query = iks_new("query"); 01236 feature = iks_new("feature"); 01237 01238 if (iq && query && feature && client) { 01239 iks_insert_attrib(iq, "from", client->user); 01240 iks_insert_attrib(iq, "to", pak->from->full); 01241 iks_insert_attrib(iq, "id", pak->id); 01242 iks_insert_attrib(iq, "type", "result"); 01243 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01244 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01245 iks_insert_node(iq, query); 01246 iks_insert_node(query, feature); 01247 ast_aji_send(client, iq); 01248 } else { 01249 ast_log(LOG_ERROR, "Out of memory.\n"); 01250 } 01251 01252 iks_delete(iq); 01253 iks_delete(query); 01254 iks_delete(feature); 01255 } 01256 01257 ASTOBJ_UNREF(client, aji_client_destroy); 01258 return IKS_FILTER_EAT; 01259 01260 }
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 2396 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.
02397 { 02398 02399 switch (cmd) { 02400 case CLI_INIT: 02401 e->command = "jabber debug [off]"; 02402 e->usage = 02403 "Usage: jabber debug [off]\n" 02404 " Enables/disables dumping of Jabber packets for debugging purposes.\n"; 02405 return NULL; 02406 case CLI_GENERATE: 02407 return NULL; 02408 } 02409 02410 if (a->argc == 2) { 02411 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02412 ASTOBJ_RDLOCK(iterator); 02413 iterator->debug = 1; 02414 ASTOBJ_UNLOCK(iterator); 02415 }); 02416 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02417 return CLI_SUCCESS; 02418 } else if (a->argc == 3) { 02419 if (!strncasecmp(a->argv[2], "off", 3)) { 02420 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02421 ASTOBJ_RDLOCK(iterator); 02422 iterator->debug = 0; 02423 ASTOBJ_UNLOCK(iterator); 02424 }); 02425 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02426 return CLI_SUCCESS; 02427 } 02428 } 02429 return CLI_SHOWUSAGE; /* defaults to invalid */ 02430 }
static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Reload jabber module.
Definition at line 2436 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.
02437 { 02438 switch (cmd) { 02439 case CLI_INIT: 02440 e->command = "jabber reload"; 02441 e->usage = 02442 "Usage: jabber reload\n" 02443 " Reloads the Jabber module.\n"; 02444 return NULL; 02445 case CLI_GENERATE: 02446 return NULL; 02447 } 02448 02449 aji_reload(1); 02450 ast_cli(a->fd, "Jabber Reloaded.\n"); 02451 return CLI_SUCCESS; 02452 }
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 2356 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.
02357 { 02358 switch (cmd) { 02359 case CLI_INIT: 02360 e->command = "jabber set debug {on|off}"; 02361 e->usage = 02362 "Usage: jabber set debug {on|off}\n" 02363 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 02364 return NULL; 02365 case CLI_GENERATE: 02366 return NULL; 02367 } 02368 02369 if (a->argc != e->args) 02370 return CLI_SHOWUSAGE; 02371 02372 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 02373 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02374 ASTOBJ_RDLOCK(iterator); 02375 iterator->debug = 1; 02376 ASTOBJ_UNLOCK(iterator); 02377 }); 02378 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02379 return CLI_SUCCESS; 02380 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 02381 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02382 ASTOBJ_RDLOCK(iterator); 02383 iterator->debug = 0; 02384 ASTOBJ_UNLOCK(iterator); 02385 }); 02386 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02387 return CLI_SUCCESS; 02388 } 02389 return CLI_SHOWUSAGE; /* defaults to invalid */ 02390 }
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 2114 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().
02115 { 02116 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02117 int flag = 0; 02118 iks *x = NULL; 02119 struct aji_buddy *buddy; 02120 02121 client->state = AJI_CONNECTED; 02122 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02123 ASTOBJ_RDLOCK(iterator); 02124 x = iks_child(pak->query); 02125 flag = 0; 02126 while (x) { 02127 if (!iks_strcmp(iks_name(x), "item")) { 02128 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02129 flag = 1; 02130 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02131 } 02132 } 02133 x = iks_next(x); 02134 } 02135 if (!flag) 02136 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02137 iks_delete(x); 02138 02139 ASTOBJ_UNLOCK(iterator); 02140 }); 02141 02142 x = iks_child(pak->query); 02143 while (x) { 02144 flag = 0; 02145 if (iks_strcmp(iks_name(x), "item") == 0) { 02146 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02147 ASTOBJ_RDLOCK(iterator); 02148 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02149 flag = 1; 02150 ASTOBJ_UNLOCK(iterator); 02151 }); 02152 02153 if (flag) { 02154 /* found buddy, don't create a new one */ 02155 x = iks_next(x); 02156 continue; 02157 } 02158 02159 buddy = ast_calloc(1, sizeof(*buddy)); 02160 if (!buddy) { 02161 ast_log(LOG_WARNING, "Out of memory\n"); 02162 return 0; 02163 } 02164 ASTOBJ_INIT(buddy); 02165 ASTOBJ_WRLOCK(buddy); 02166 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02167 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02168 if(ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02169 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 02170 ASTOBJ_MARK(buddy); 02171 } else if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 02172 /* subscribe to buddy's presence only 02173 if we really need to */ 02174 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 02175 } 02176 ASTOBJ_UNLOCK(buddy); 02177 if (buddy) { 02178 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 02179 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02180 } 02181 } 02182 x = iks_next(x); 02183 } 02184 02185 iks_delete(x); 02186 aji_pruneregister(client); 02187 02188 ASTOBJ_UNREF(client, aji_client_destroy); 02189 return IKS_FILTER_EAT; 02190 }
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 2219 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().
02220 { 02221 iks *roster = NULL; 02222 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 02223 02224 if(roster) { 02225 iks_insert_attrib(roster, "id", "roster"); 02226 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 02227 ast_aji_send(client, roster); 02228 } 02229 02230 iks_delete(roster); 02231 02232 return 1; 02233 }
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 1468 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 1478 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().
01479 { 01480 struct aji_message *insert, *tmp; 01481 int flag = 0; 01482 01483 if (!(insert = ast_calloc(1, sizeof(*insert)))) 01484 return; 01485 time(&insert->arrived); 01486 if (iks_find_cdata(pak->x, "body")) 01487 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 01488 if (pak->id) 01489 ast_copy_string(insert->id, pak->id, sizeof(insert->message)); 01490 if (pak->from) 01491 insert->from = ast_strdup(pak->from->full); 01492 AST_LIST_LOCK(&client->messages); 01493 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 01494 if (flag) { 01495 AST_LIST_REMOVE_CURRENT(list); 01496 if (tmp->from) 01497 ast_free(tmp->from); 01498 if (tmp->message) 01499 ast_free(tmp->message); 01500 } else if (difftime(time(NULL), tmp->arrived) >= client->message_timeout) { 01501 flag = 1; 01502 AST_LIST_REMOVE_CURRENT(list); 01503 if (tmp->from) 01504 ast_free(tmp->from); 01505 if (tmp->message) 01506 ast_free(tmp->message); 01507 } 01508 } 01509 AST_LIST_TRAVERSE_SAFE_END; 01510 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 01511 AST_LIST_UNLOCK(&client->messages); 01512 }
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 1518 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().
01519 { 01520 int status, priority; 01521 struct aji_buddy *buddy; 01522 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 01523 char *ver, *node, *descrip, *type; 01524 01525 if(client->state != AJI_CONNECTED) 01526 aji_create_buddy(pak->from->partial, client); 01527 01528 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01529 if (!buddy && pak->from->partial) { 01530 /* allow our jid to be used to log in with another resource */ 01531 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 01532 aji_create_buddy(pak->from->partial, client); 01533 else 01534 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 01535 return; 01536 } 01537 type = iks_find_attrib(pak->x, "type"); 01538 if(client->component && type &&!strcasecmp("probe", type)) { 01539 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01540 ast_verbose("what i was looking for \n"); 01541 } 01542 ASTOBJ_WRLOCK(buddy); 01543 status = (pak->show) ? pak->show : 6; 01544 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 01545 tmp = buddy->resources; 01546 descrip = ast_strdup(iks_find_cdata(pak->x,"status")); 01547 01548 while (tmp && pak->from->resource) { 01549 if (!strcasecmp(tmp->resource, pak->from->resource)) { 01550 tmp->status = status; 01551 if (tmp->description) ast_free(tmp->description); 01552 tmp->description = descrip; 01553 found = tmp; 01554 if (status == 6) { /* Sign off Destroy resource */ 01555 if (last && found->next) { 01556 last->next = found->next; 01557 } else if (!last) { 01558 if (found->next) 01559 buddy->resources = found->next; 01560 else 01561 buddy->resources = NULL; 01562 } else if (!found->next) { 01563 if (last) 01564 last->next = NULL; 01565 else 01566 buddy->resources = NULL; 01567 } 01568 ast_free(found); 01569 found = NULL; 01570 break; 01571 } 01572 /* resource list is sorted by descending priority */ 01573 if (tmp->priority != priority) { 01574 found->priority = priority; 01575 if (!last && !found->next) 01576 /* resource was found to be unique, 01577 leave loop */ 01578 break; 01579 /* search for resource in our list 01580 and take it out for the moment */ 01581 if (last) 01582 last->next = found->next; 01583 else 01584 buddy->resources = found->next; 01585 01586 last = NULL; 01587 tmp = buddy->resources; 01588 if (!buddy->resources) 01589 buddy->resources = found; 01590 /* priority processing */ 01591 while (tmp) { 01592 /* insert resource back according to 01593 its priority value */ 01594 if (found->priority > tmp->priority) { 01595 if (last) 01596 /* insert within list */ 01597 last->next = found; 01598 found->next = tmp; 01599 if (!last) 01600 /* insert on top */ 01601 buddy->resources = found; 01602 break; 01603 } 01604 if (!tmp->next) { 01605 /* insert at the end of the list */ 01606 tmp->next = found; 01607 found->next = NULL; 01608 break; 01609 } 01610 last = tmp; 01611 tmp = tmp->next; 01612 } 01613 } 01614 break; 01615 } 01616 last = tmp; 01617 tmp = tmp->next; 01618 } 01619 01620 /* resource not found in our list, create it */ 01621 if (!found && status != 6 && pak->from->resource) { 01622 found = ast_calloc(1, sizeof(*found)); 01623 01624 if (!found) { 01625 ast_log(LOG_ERROR, "Out of memory!\n"); 01626 return; 01627 } 01628 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 01629 found->status = status; 01630 found->description = descrip; 01631 found->priority = priority; 01632 found->next = NULL; 01633 last = NULL; 01634 tmp = buddy->resources; 01635 while (tmp) { 01636 if (found->priority > tmp->priority) { 01637 if (last) 01638 last->next = found; 01639 found->next = tmp; 01640 if (!last) 01641 buddy->resources = found; 01642 break; 01643 } 01644 if (!tmp->next) { 01645 tmp->next = found; 01646 break; 01647 } 01648 last = tmp; 01649 tmp = tmp->next; 01650 } 01651 if (!tmp) 01652 buddy->resources = found; 01653 } 01654 01655 ASTOBJ_UNLOCK(buddy); 01656 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 01657 01658 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 01659 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 01660 01661 /* handle gmail client's special caps:c tag */ 01662 if (!node && !ver) { 01663 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 01664 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 01665 } 01666 01667 /* retrieve capabilites of the new resource */ 01668 if(status !=6 && found && !found->cap) { 01669 found->cap = aji_find_version(node, ver, pak); 01670 if(gtalk_yuck(pak->x)) /* gtalk should do discover */ 01671 found->cap->jingle = 1; 01672 if(found->cap->jingle && option_debug > 4) { 01673 ast_debug(1,"Special case for google till they support discover.\n"); 01674 } 01675 else { 01676 iks *iq, *query; 01677 iq = iks_new("iq"); 01678 query = iks_new("query"); 01679 if(query && iq) { 01680 iks_insert_attrib(iq, "type", "get"); 01681 iks_insert_attrib(iq, "to", pak->from->full); 01682 iks_insert_attrib(iq,"from", client->jid->full); 01683 iks_insert_attrib(iq, "id", client->mid); 01684 ast_aji_increment_mid(client->mid); 01685 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01686 iks_insert_node(iq, query); 01687 ast_aji_send(client, iq); 01688 01689 } else 01690 ast_log(LOG_ERROR, "Out of memory.\n"); 01691 01692 iks_delete(query); 01693 iks_delete(iq); 01694 } 01695 } 01696 switch (pak->subtype) { 01697 case IKS_TYPE_AVAILABLE: 01698 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 01699 break; 01700 case IKS_TYPE_UNAVAILABLE: 01701 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 01702 break; 01703 default: 01704 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 01705 } 01706 switch (pak->show) { 01707 case IKS_SHOW_UNAVAILABLE: 01708 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01709 break; 01710 case IKS_SHOW_AVAILABLE: 01711 ast_debug(3, "JABBER: type is available\n"); 01712 break; 01713 case IKS_SHOW_CHAT: 01714 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01715 break; 01716 case IKS_SHOW_AWAY: 01717 ast_debug(3, "JABBER: type is away\n"); 01718 break; 01719 case IKS_SHOW_XA: 01720 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01721 break; 01722 case IKS_SHOW_DND: 01723 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 01724 break; 01725 default: 01726 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 01727 } 01728 }
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 1736 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().
01737 { 01738 iks *presence = NULL, *status = NULL; 01739 struct aji_buddy* buddy = NULL; 01740 01741 switch (pak->subtype) { 01742 case IKS_TYPE_SUBSCRIBE: 01743 presence = iks_new("presence"); 01744 status = iks_new("status"); 01745 if (presence && status) { 01746 iks_insert_attrib(presence, "type", "subscribed"); 01747 iks_insert_attrib(presence, "to", pak->from->full); 01748 iks_insert_attrib(presence, "from", client->jid->full); 01749 if (pak->id) 01750 iks_insert_attrib(presence, "id", pak->id); 01751 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 01752 iks_insert_node(presence, status); 01753 ast_aji_send(client, presence); 01754 } else 01755 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 01756 01757 iks_delete(presence); 01758 iks_delete(status); 01759 01760 if (client->component) 01761 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 01762 case IKS_TYPE_SUBSCRIBED: 01763 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01764 if (!buddy && pak->from->partial) { 01765 aji_create_buddy(pak->from->partial, client); 01766 } 01767 default: 01768 if (option_verbose > 4) { 01769 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 01770 } 01771 } 01772 }
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 2267 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().
02268 { 02269 int connected = IKS_NET_NOCONN; 02270 02271 #ifdef HAVE_OPENSSL 02272 /* reset stream flags */ 02273 client->stream_flags = 0; 02274 #endif 02275 /* If it's a component, connect to user, otherwise, connect to server */ 02276 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 02277 02278 if (connected == IKS_NET_NOCONN) { 02279 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 02280 return IKS_HOOK; 02281 } else if (connected == IKS_NET_NODNS) { 02282 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server)); 02283 return IKS_HOOK; 02284 } 02285 02286 return IKS_OK; 02287 }
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 2869 of file res_jabber.c.
References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, debug, globalflags, JABBER_CONFIG, LOG_WARNING, and var.
Referenced by aji_reload().
02870 { 02871 char *cat = NULL; 02872 int debug = 1; 02873 struct ast_config *cfg = NULL; 02874 struct ast_variable *var = NULL; 02875 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02876 02877 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 02878 return -1; 02879 02880 /* Reset flags to default value */ 02881 ast_set_flag(&globalflags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02882 02883 if (!cfg) { 02884 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 02885 return 0; 02886 } 02887 02888 cat = ast_category_browse(cfg, NULL); 02889 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 02890 if (!strcasecmp(var->name, "debug")) 02891 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 02892 else if (!strcasecmp(var->name, "autoprune")) 02893 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 02894 else if (!strcasecmp(var->name, "autoregister")) 02895 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 02896 } 02897 02898 while (cat) { 02899 if (strcasecmp(cat, "general")) { 02900 var = ast_variable_browse(cfg, cat); 02901 aji_create_client(cat, var, debug); 02902 } 02903 cat = ast_category_browse(cfg, cat); 02904 } 02905 ast_config_destroy(cfg); /* or leak memory */ 02906 return 1; 02907 }
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 777 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().
00778 { 00779 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 00780 00781 if (!ast_strlen_zero(xmpp)) 00782 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 00783 00784 if (client->debug) { 00785 if (is_incoming) 00786 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 00787 else { 00788 if( strlen(xmpp) == 1) { 00789 if(option_debug > 2 && xmpp[0] == ' ') { 00790 ast_verbose("\nJABBER: Keep alive packet\n"); 00791 } 00792 } else 00793 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 00794 } 00795 00796 } 00797 ASTOBJ_UNREF(client, aji_client_destroy); 00798 }
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 2060 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.
02061 { 02062 int res = 0; 02063 iks *removeiq = iks_new("iq"); 02064 iks *removequery = iks_new("query"); 02065 iks *removeitem = iks_new("item"); 02066 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02067 if (!client || !removeiq || !removequery || !removeitem || !send) { 02068 ast_log(LOG_ERROR, "Out of memory.\n"); 02069 goto safeout; 02070 } 02071 02072 iks_insert_node(removeiq, removequery); 02073 iks_insert_node(removequery, removeitem); 02074 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02075 ASTOBJ_RDLOCK(iterator); 02076 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02077 * be called at the same time */ 02078 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { 02079 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02080 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02081 " so I am no longer subscribing to your presence.\n")); 02082 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02083 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02084 " your access to my presence.\n")); 02085 iks_insert_attrib(removeiq, "from", client->jid->full); 02086 iks_insert_attrib(removeiq, "type", "set"); 02087 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02088 iks_insert_attrib(removeitem, "jid", iterator->name); 02089 iks_insert_attrib(removeitem, "subscription", "remove"); 02090 res = ast_aji_send(client, removeiq); 02091 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02092 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02093 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02094 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02095 } 02096 ASTOBJ_UNLOCK(iterator); 02097 }); 02098 02099 safeout: 02100 iks_delete(removeiq); 02101 iks_delete(removequery); 02102 iks_delete(removeitem); 02103 iks_delete(send); 02104 02105 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); 02106 }
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 2197 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().
02198 { 02199 int res = 0; 02200 02201 if (client->state) 02202 client->state = AJI_DISCONNECTED; 02203 client->timeout=50; 02204 if (client->p) 02205 iks_parser_reset(client->p); 02206 if (client->authorized) 02207 client->authorized = 0; 02208 02209 res = aji_initialize(client); 02210 02211 return res; 02212 }
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 - 1, 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 if (ret != IKS_OK) { 00692 ast_log(LOG_WARNING, "XML parsing failed\n"); 00693 return ret; 00694 } 00695 ast_debug(3, "XML parsing successful\n"); 00696 } 00697 return IKS_OK; 00698 }
static void * aji_recv_loop | ( | void * | data | ) | [static] |
receive message loop.
data | void |
Definition at line 1899 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().
01900 { 01901 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01902 int res = IKS_HOOK; 01903 01904 while(res != IKS_OK) { 01905 ast_debug(3, "JABBER: Connecting.\n"); 01906 res = aji_reconnect(client); 01907 sleep(4); 01908 } 01909 01910 do { 01911 if (res == IKS_NET_RWERR || client->timeout == 0) { 01912 while(res != IKS_OK) { 01913 ast_debug(3, "JABBER: reconnecting.\n"); 01914 res = aji_reconnect(client); 01915 sleep(4); 01916 } 01917 } 01918 01919 res = aji_recv(client, 1); 01920 01921 if (client->state == AJI_DISCONNECTING) { 01922 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 01923 pthread_exit(NULL); 01924 } 01925 01926 /* Decrease timeout if no data received */ 01927 if (res == IKS_NET_EXPIRED) 01928 client->timeout--; 01929 01930 if (res == IKS_HOOK) 01931 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 01932 else if (res == IKS_NET_TLSFAIL) 01933 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 01934 else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 01935 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 01936 if(res == IKS_OK) 01937 client->timeout = 50; 01938 else 01939 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 01940 } else if (res == IKS_NET_RWERR) 01941 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 01942 } while (client); 01943 ASTOBJ_UNREF(client, aji_client_destroy); 01944 return 0; 01945 }
static int aji_register_approve_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Unknown.
data | void | |
pak | ikspak |
Definition at line 1058 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().
01059 { 01060 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01061 iks *iq = NULL, *presence = NULL, *x = NULL; 01062 01063 iq = iks_new("iq"); 01064 presence = iks_new("presence"); 01065 x = iks_new("x"); 01066 if (client && iq && presence && x) { 01067 if (!iks_find(pak->query, "remove")) { 01068 iks_insert_attrib(iq, "from", client->jid->full); 01069 iks_insert_attrib(iq, "to", pak->from->full); 01070 iks_insert_attrib(iq, "id", pak->id); 01071 iks_insert_attrib(iq, "type", "result"); 01072 ast_aji_send(client, iq); 01073 01074 iks_insert_attrib(presence, "from", client->jid->full); 01075 iks_insert_attrib(presence, "to", pak->from->partial); 01076 iks_insert_attrib(presence, "id", client->mid); 01077 ast_aji_increment_mid(client->mid); 01078 iks_insert_attrib(presence, "type", "subscribe"); 01079 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01080 iks_insert_node(presence, x); 01081 ast_aji_send(client, presence); 01082 } 01083 } else { 01084 ast_log(LOG_ERROR, "Out of memory.\n"); 01085 } 01086 01087 01088 iks_delete(iq); 01089 iks_delete(presence); 01090 iks_delete(x); 01091 01092 ASTOBJ_UNREF(client, aji_client_destroy); 01093 return IKS_FILTER_EAT; 01094 }
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 1101 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().
01102 { 01103 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01104 struct aji_buddy *buddy = NULL; 01105 char *node = NULL; 01106 iks *iq = NULL, *query = NULL; 01107 01108 client = (struct aji_client *) data; 01109 01110 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01111 if (!buddy) { 01112 iks *error = NULL, *notacceptable = NULL; 01113 01114 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01115 iq = iks_new("iq"); 01116 query = iks_new("query"); 01117 error = iks_new("error"); 01118 notacceptable = iks_new("not-acceptable"); 01119 if(iq && query && error && notacceptable) { 01120 iks_insert_attrib(iq, "type", "error"); 01121 iks_insert_attrib(iq, "from", client->user); 01122 iks_insert_attrib(iq, "to", pak->from->full); 01123 iks_insert_attrib(iq, "id", pak->id); 01124 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01125 iks_insert_attrib(error, "code" , "406"); 01126 iks_insert_attrib(error, "type", "modify"); 01127 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01128 iks_insert_node(iq, query); 01129 iks_insert_node(iq, error); 01130 iks_insert_node(error, notacceptable); 01131 ast_aji_send(client, iq); 01132 } else { 01133 ast_log(LOG_ERROR, "Out of memory.\n"); 01134 } 01135 01136 iks_delete(error); 01137 iks_delete(notacceptable); 01138 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01139 iks *instructions = NULL; 01140 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01141 iq = iks_new("iq"); 01142 query = iks_new("query"); 01143 instructions = iks_new("instructions"); 01144 if (iq && query && instructions && client) { 01145 iks_insert_attrib(iq, "from", client->user); 01146 iks_insert_attrib(iq, "to", pak->from->full); 01147 iks_insert_attrib(iq, "id", pak->id); 01148 iks_insert_attrib(iq, "type", "result"); 01149 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01150 iks_insert_cdata(instructions, explain, 0); 01151 iks_insert_node(iq, query); 01152 iks_insert_node(query, instructions); 01153 ast_aji_send(client, iq); 01154 } else { 01155 ast_log(LOG_ERROR, "Out of memory.\n"); 01156 } 01157 01158 iks_delete(instructions); 01159 } 01160 iks_delete(iq); 01161 iks_delete(query); 01162 ASTOBJ_UNREF(client, aji_client_destroy); 01163 return IKS_FILTER_EAT; 01164 }
static int aji_reload | ( | int | reload | ) | [static] |
Reload the jabber module.
Definition at line 2996 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().
02997 { 02998 int res; 02999 03000 ASTOBJ_CONTAINER_MARKALL(&clients); 03001 if (!(res = aji_load_config(reload))) { 03002 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 03003 return 0; 03004 } else if (res == -1) 03005 return 1; 03006 03007 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); 03008 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03009 ASTOBJ_RDLOCK(iterator); 03010 if(iterator->state == AJI_DISCONNECTED) { 03011 if (!iterator->thread) 03012 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 03013 } else if (iterator->state == AJI_CONNECTING) 03014 aji_get_roster(iterator); 03015 ASTOBJ_UNLOCK(iterator); 03016 }); 03017 03018 return 1; 03019 }
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 706 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().
00707 { 00708 char *msg; 00709 int len, err; 00710 00711 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 00712 msg = iks_malloc(len); 00713 if (!msg) 00714 return IKS_NOMEM; 00715 sprintf(msg, "<?xml version='1.0'?>" 00716 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 00717 "%s' to='%s' version='1.0'>", client->name_space, to); 00718 err = aji_send_raw(client, msg); 00719 iks_free(msg); 00720 if (err != IKS_OK) 00721 return err; 00722 00723 return IKS_OK; 00724 }
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 745 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().
00746 { 00747 int ret; 00748 #ifdef HAVE_OPENSSL 00749 int len = strlen(xmlstr); 00750 00751 if (aji_is_secure(client)) { 00752 ret = SSL_write(client->ssl_session, xmlstr, len); 00753 if (ret) { 00754 /* Log the message here, because iksemel's logHook is 00755 unaccessible */ 00756 aji_log_hook(client, xmlstr, len, 0); 00757 return IKS_OK; 00758 } 00759 } 00760 #endif 00761 /* If needed, data will be sent unencrypted, and logHook will 00762 be called inside iks_send_raw */ 00763 ret = iks_send_raw(client->p, xmlstr); 00764 if (ret != IKS_OK) 00765 return ret; 00766 00767 return IKS_OK; 00768 }
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 2322 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().
02323 { 02324 int res = 0; 02325 iks *presence = iks_make_pres(level, desc); 02326 iks *cnode = iks_new("c"); 02327 iks *priority = iks_new("priority"); 02328 char priorityS[10]; 02329 02330 if (presence && cnode && client && priority) { 02331 if(to) 02332 iks_insert_attrib(presence, "to", to); 02333 if(from) 02334 iks_insert_attrib(presence, "from", from); 02335 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 02336 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 02337 iks_insert_node(presence, priority); 02338 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 02339 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 02340 iks_insert_attrib(cnode, "ext", "voice-v1"); 02341 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 02342 iks_insert_node(presence, cnode); 02343 res = ast_aji_send(client, presence); 02344 } else 02345 ast_log(LOG_ERROR, "Out of memory.\n"); 02346 02347 iks_delete(cnode); 02348 iks_delete(presence); 02349 iks_delete(priority); 02350 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show buddy lists.
Definition at line 2503 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.
02504 { 02505 struct aji_resource *resource; 02506 struct aji_client *client; 02507 02508 switch (cmd) { 02509 case CLI_INIT: 02510 e->command = "jabber show buddies"; 02511 e->usage = 02512 "Usage: jabber show buddies\n" 02513 " Shows buddy lists of our clients\n"; 02514 return NULL; 02515 case CLI_GENERATE: 02516 return NULL; 02517 } 02518 02519 ast_cli(a->fd, "Jabber buddy lists\n"); 02520 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02521 ast_cli(a->fd,"Client: %s\n", iterator->user); 02522 client = iterator; 02523 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02524 ASTOBJ_RDLOCK(iterator); 02525 ast_cli(a->fd,"\tBuddy:\t%s\n", iterator->name); 02526 if (!iterator->resources) 02527 ast_cli(a->fd,"\t\tResource: None\n"); 02528 for (resource = iterator->resources; resource; resource = resource->next) { 02529 ast_cli(a->fd,"\t\tResource: %s\n", resource->resource); 02530 if(resource->cap) { 02531 ast_cli(a->fd,"\t\t\tnode: %s\n", resource->cap->parent->node); 02532 ast_cli(a->fd,"\t\t\tversion: %s\n", resource->cap->version); 02533 ast_cli(a->fd,"\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 02534 } 02535 ast_cli(a->fd,"\t\tStatus: %d\n", resource->status); 02536 ast_cli(a->fd,"\t\tPriority: %d\n", resource->priority); 02537 } 02538 ASTOBJ_UNLOCK(iterator); 02539 }); 02540 iterator = client; 02541 }); 02542 return CLI_SUCCESS; 02543 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Show client status.
Definition at line 2458 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.
02459 { 02460 char *status; 02461 int count = 0; 02462 02463 switch (cmd) { 02464 case CLI_INIT: 02465 e->command = "jabber show connected"; 02466 e->usage = 02467 "Usage: jabber show connected\n" 02468 " Shows state of clients and components\n"; 02469 return NULL; 02470 case CLI_GENERATE: 02471 return NULL; 02472 } 02473 02474 ast_cli(a->fd, "Jabber Users and their status:\n"); 02475 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02476 ASTOBJ_RDLOCK(iterator); 02477 count++; 02478 switch (iterator->state) { 02479 case AJI_DISCONNECTED: 02480 status = "Disconnected"; 02481 break; 02482 case AJI_CONNECTING: 02483 status = "Connecting"; 02484 break; 02485 case AJI_CONNECTED: 02486 status = "Connected"; 02487 break; 02488 default: 02489 status = "Unknown"; 02490 } 02491 ast_cli(a->fd, " User: %s - %s\n", iterator->user, status); 02492 ASTOBJ_UNLOCK(iterator); 02493 }); 02494 ast_cli(a->fd, "----\n"); 02495 ast_cli(a->fd, " Number of users: %d\n", count); 02496 return CLI_SUCCESS; 02497 }
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 809 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().
00810 { 00811 iks *x = NULL; 00812 int len; 00813 char *s; 00814 char *base64; 00815 00816 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 00817 iks_start_sasl is an iksemel API function and relies on GnuTLS, 00818 whereas we use OpenSSL */ 00819 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 00820 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 00821 if (!(type & IKS_STREAM_SASL_PLAIN)) { 00822 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 00823 return IKS_NET_NOTSUPP; 00824 } 00825 00826 x = iks_new("auth"); 00827 if (!x) { 00828 ast_log(LOG_ERROR, "Out of memory.\n"); 00829 return IKS_NET_NOTSUPP; 00830 } 00831 00832 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 00833 len = strlen(username) + strlen(pass) + 3; 00834 s = alloca(len); 00835 base64 = alloca((len + 2) * 4 / 3); 00836 iks_insert_attrib(x, "mechanism", "PLAIN"); 00837 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 00838 00839 /* exclude the NULL training byte from the base64 encoding operation 00840 as some XMPP servers will refuse it. 00841 The format for authentication is [authzid]\0authcid\0password 00842 not [authzid]\0authcid\0password\0 */ 00843 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 00844 iks_insert_cdata(x, base64, 0); 00845 ast_aji_send(client, x); 00846 iks_delete(x); 00847 00848 return IKS_OK; 00849 }
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 2549 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.
02550 { 02551 struct aji_client *client; 02552 struct aji_resource *resource; 02553 const char *name = "asterisk"; 02554 struct aji_message *tmp; 02555 02556 switch (cmd) { 02557 case CLI_INIT: 02558 e->command = "jabber test"; 02559 e->usage = 02560 "Usage: jabber test [client]\n" 02561 " Sends test message for debugging purposes. A specific client\n" 02562 " as configured in jabber.conf can be optionally specified.\n"; 02563 return NULL; 02564 case CLI_GENERATE: 02565 return NULL; 02566 } 02567 02568 if (a->argc > 3) 02569 return CLI_SHOWUSAGE; 02570 else if (a->argc == 3) 02571 name = a->argv[2]; 02572 02573 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 02574 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 02575 return CLI_FAILURE; 02576 } 02577 02578 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 02579 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 02580 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02581 ASTOBJ_RDLOCK(iterator); 02582 ast_verbose("User: %s\n", iterator->name); 02583 for (resource = iterator->resources; resource; resource = resource->next) { 02584 ast_verbose("Resource: %s\n", resource->resource); 02585 if(resource->cap) { 02586 ast_verbose(" client: %s\n", resource->cap->parent->node); 02587 ast_verbose(" version: %s\n", resource->cap->version); 02588 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 02589 } 02590 ast_verbose(" Priority: %d\n", resource->priority); 02591 ast_verbose(" Status: %d\n", resource->status); 02592 ast_verbose(" Message: %s\n", S_OR(resource->description,"")); 02593 } 02594 ASTOBJ_UNLOCK(iterator); 02595 }); 02596 ast_verbose("\nOooh a working message stack!\n"); 02597 AST_LIST_LOCK(&client->messages); 02598 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 02599 ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 02600 } 02601 AST_LIST_UNLOCK(&client->messages); 02602 ASTOBJ_UNREF(client, aji_client_destroy); 02603 02604 return CLI_SUCCESS; 02605 }
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 1808 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01809 { 01810 int res = 0; 01811 iks *iq = NULL; 01812 iq = iks_new("iq"); 01813 01814 if (iq && client) { 01815 iks_insert_attrib(iq, "type", "get"); 01816 iks_insert_attrib(iq, "to", server); 01817 iks_insert_attrib(iq, "id", client->mid); 01818 ast_aji_increment_mid(client->mid); 01819 ast_aji_send(client, iq); 01820 } else 01821 ast_log(LOG_ERROR, "Out of memory.\n"); 01822 01823 iks_delete(iq); 01824 01825 return res; 01826 }
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 2294 of file res_jabber.c.
References aji_client_destroy(), ast_verb, ASTOBJ_UNREF, and aji_client::p.
Referenced by unload_module().
02295 { 02296 if (client) { 02297 ast_verb(4, "JABBER: Disconnecting\n"); 02298 #ifdef HAVE_OPENSSL 02299 if (client->stream_flags & SECURE) { 02300 SSL_shutdown(client->ssl_session); 02301 SSL_CTX_free(client->ssl_context); 02302 SSL_free(client->ssl_session); 02303 } 02304 #endif 02305 iks_disconnect(client->p); 02306 iks_parser_delete(client->p); 02307 ASTOBJ_UNREF(client, aji_client_destroy); 02308 } 02309 02310 return 1; 02311 }
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 2915 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().
02916 { 02917 struct aji_client *client = NULL; 02918 char *aux = NULL; 02919 02920 client = ASTOBJ_CONTAINER_FIND(&clients, name); 02921 if (!client && strchr(name, '@')) { 02922 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02923 aux = ast_strdupa(iterator->user); 02924 if (strchr(aux, '/')) { 02925 /* strip resource for comparison */ 02926 aux = strsep(&aux, "/"); 02927 } 02928 if (!strncasecmp(aux, name, strlen(aux))) { 02929 client = iterator; 02930 } 02931 }); 02932 } 02933 02934 return client; 02935 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) |
Definition at line 2937 of file res_jabber.c.
References clients.
02938 { 02939 return &clients; 02940 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 1952 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().
01953 { 01954 int i = 0; 01955 01956 for (i = strlen(mid) - 1; i >= 0; i--) { 01957 if (mid[i] != 'z') { 01958 mid[i] = mid[i] + 1; 01959 i = 0; 01960 } else 01961 mid[i] = 'a'; 01962 } 01963 }
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 1865 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
01866 { 01867 int res = 0; 01868 iks *invite, *body, *namespace; 01869 01870 invite = iks_new("message"); 01871 body = iks_new("body"); 01872 namespace = iks_new("x"); 01873 if (client && invite && body && namespace) { 01874 iks_insert_attrib(invite, "to", user); 01875 iks_insert_attrib(invite, "id", client->mid); 01876 ast_aji_increment_mid(client->mid); 01877 iks_insert_cdata(body, message, 0); 01878 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 01879 iks_insert_attrib(namespace, "jid", room); 01880 iks_insert_node(invite, body); 01881 iks_insert_node(invite, namespace); 01882 res = ast_aji_send(client, invite); 01883 } else 01884 ast_log(LOG_ERROR, "Out of memory.\n"); 01885 01886 iks_delete(body); 01887 iks_delete(namespace); 01888 iks_delete(invite); 01889 01890 return res; 01891 }
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 1834 of file res_jabber.c.
References ast_aji_send(), ast_log(), and LOG_ERROR.
01835 { 01836 int res = 0; 01837 iks *presence = NULL, *priority = NULL; 01838 presence = iks_new("presence"); 01839 priority = iks_new("priority"); 01840 if (presence && priority && client) { 01841 iks_insert_cdata(priority, "0", 1); 01842 iks_insert_attrib(presence, "to", room); 01843 iks_insert_node(presence, priority); 01844 res = ast_aji_send(client, presence); 01845 iks_insert_cdata(priority, "5", 1); 01846 iks_insert_attrib(presence, "to", room); 01847 res = ast_aji_send(client, presence); 01848 } else 01849 ast_log(LOG_ERROR, "Out of memory.\n"); 01850 01851 iks_delete(presence); 01852 iks_delete(priority); 01853 01854 return res; 01855 }
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 732 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().
00733 { 00734 return aji_send_raw(client, iks_string(iks_stack(x), x)); 00735 }
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 1781 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().
01782 { 01783 int res = 0; 01784 iks *message_packet = NULL; 01785 if (client->state == AJI_CONNECTED) { 01786 message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message); 01787 if (message_packet) { 01788 iks_insert_attrib(message_packet, "from", client->jid->full); 01789 res = ast_aji_send(client, message_packet); 01790 } else { 01791 ast_log(LOG_ERROR, "Out of memory.\n"); 01792 } 01793 01794 iks_delete(message_packet); 01795 } else 01796 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 01797 return 1; 01798 }
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 3046 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.
03047 { 03048 ASTOBJ_CONTAINER_INIT(&clients); 03049 if(!aji_reload(0)) 03050 return AST_MODULE_LOAD_DECLINE; 03051 ast_manager_register2("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send, 03052 "Sends a message to a Jabber Client", mandescr_jabber_send); 03053 ast_register_application(app_ajisend, aji_send_exec, ajisend_synopsis, ajisend_descrip); 03054 ast_register_application(app_ajistatus, aji_status_exec, ajistatus_synopsis, ajistatus_descrip); 03055 ast_cli_register_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); 03056 ast_custom_function_register(&jabberstatus_function); 03057 03058 return 0; 03059 }
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 2955 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().
02956 { 02957 struct aji_client *client = NULL; 02958 const char *id = astman_get_header(m,"ActionID"); 02959 const char *jabber = astman_get_header(m,"Jabber"); 02960 const char *screenname = astman_get_header(m,"ScreenName"); 02961 const char *message = astman_get_header(m,"Message"); 02962 02963 if (ast_strlen_zero(jabber)) { 02964 astman_send_error(s, m, "No transport specified"); 02965 return 0; 02966 } 02967 if (ast_strlen_zero(screenname)) { 02968 astman_send_error(s, m, "No ScreenName specified"); 02969 return 0; 02970 } 02971 if (ast_strlen_zero(message)) { 02972 astman_send_error(s, m, "No Message specified"); 02973 return 0; 02974 } 02975 02976 astman_send_ack(s, m, "Attempting to send Jabber Message"); 02977 client = ast_aji_get_client(jabber); 02978 if (!client) { 02979 astman_send_error(s, m, "Could not find Sender"); 02980 return 0; 02981 } 02982 if (strchr(screenname, '@') && message){ 02983 ast_aji_send_chat(client, screenname, message); 02984 astman_append(s, "Response: Success\r\n"); 02985 if (!ast_strlen_zero(id)) 02986 astman_append(s, "ActionID: %s\r\n",id); 02987 return 0; 02988 } 02989 astman_append(s, "Response: Error\r\n"); 02990 if (!ast_strlen_zero(id)) 02991 astman_append(s, "ActionID: %s\r\n",id); 02992 return 0; 02993 }
static int reload | ( | void | ) | [static] |
Wrapper for aji_reload.
Definition at line 3062 of file res_jabber.c.
References aji_reload().
03063 { 03064 aji_reload(1); 03065 return 0; 03066 }
static int unload_module | ( | void | ) | [static] |
Unload the jabber module.
Definition at line 3022 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.
03023 { 03024 03025 ast_cli_unregister_multiple(aji_cli, sizeof(aji_cli) / sizeof(struct ast_cli_entry)); 03026 ast_unregister_application(app_ajisend); 03027 ast_unregister_application(app_ajistatus); 03028 ast_manager_unregister("JabberSend"); 03029 ast_custom_function_unregister(&jabberstatus_function); 03030 03031 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03032 ASTOBJ_RDLOCK(iterator); 03033 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 03034 iterator->state = AJI_DISCONNECTING; 03035 ast_aji_disconnect(iterator); 03036 pthread_join(iterator->thread, NULL); 03037 ASTOBJ_UNLOCK(iterator); 03038 }); 03039 03040 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); 03041 ASTOBJ_CONTAINER_DESTROY(&clients); 03042 return 0; 03043 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3072 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
char* ajisend_descrip [static] |
Initial value:
"JabberSend(Jabber,ScreenName,Message)\n" " Jabber - Client or transport Asterisk uses to connect to Jabber\n" " ScreenName - XMPP/Jabber JID (Name) of recipient\n" " Message - Message to be sent to the budd (UTF8)y\n"
Definition at line 139 of file res_jabber.c.
char* ajisend_synopsis = "JabberSend(jabber,screenname,message)" [static] |
Definition at line 137 of file res_jabber.c.
char* ajistatus_descrip [static] |
Definition at line 149 of file res_jabber.c.
char* ajistatus_synopsis = "JabberStatus(Jabber,ScreenName,Variable)" [static] |
Definition at line 147 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 135 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 145 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3072 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL |
struct ast_cli_entry cli_aji_do_debug_deprecated = { .handler = aji_do_debug_deprecated , .summary = "Enable/disable jabber debugging" ,__VA_ARGS__ } [static] |
Definition at line 126 of file res_jabber.c.
struct aji_client_container clients |
Definition at line 158 of file res_jabber.c.
Referenced by aji_create_client(), aji_do_debug_deprecated(), aji_do_set_debug(), aji_reload(), aji_show_buddies(), aji_show_clients(), aji_test(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), jingle_load_config(), load_module(), and unload_module().
struct ast_flags globalflags = { AJI_AUTOPRUNE | AJI_AUTOREGISTER } [static] |
struct ast_custom_function jabberstatus_function [static] |
char mandescr_jabber_send[] [static] |