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

Go to the source code of this file.
Defines | |
| #define | JABBER_CONFIG "jabber.conf" |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | acf_jabberreceive_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
| 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) |
| static void | aji_buddy_destroy (struct aji_buddy *obj) |
| static int | aji_client_connect (void *data, ikspak *pak) |
| static void | aji_client_destroy (struct aji_client *obj) |
| static int | aji_client_info_handler (void *data, ikspak *pak) |
| static int | aji_create_buddy (char *label, struct aji_client *client) |
| static int | aji_create_client (char *label, struct ast_variable *var, int debug) |
| static int | aji_dinfo_handler (void *data, ikspak *pak) |
| static int | aji_ditems_handler (void *data, ikspak *pak) |
| static char * | aji_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | aji_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | aji_filter_roster (void *data, ikspak *pak) |
| static struct aji_resource * | aji_find_resource (struct aji_buddy *buddy, char *name) |
| static struct aji_version * | aji_find_version (char *node, char *version, ikspak *pak) |
| static int | aji_get_roster (struct aji_client *client) |
| static void | aji_handle_iq (struct aji_client *client, iks *node) |
| static void | aji_handle_message (struct aji_client *client, ikspak *pak) |
| static void | aji_handle_presence (struct aji_client *client, ikspak *pak) |
| static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
| static int | aji_initialize (struct aji_client *client) |
| static int | aji_io_recv (struct aji_client *client, char *buffer, size_t buf_len, int timeout) |
| static int | aji_is_secure (struct aji_client *client) |
| static int | aji_load_config (int reload) |
| static void | aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming) |
| static void | aji_message_destroy (struct aji_message *obj) |
| static void | aji_pruneregister (struct aji_client *client) |
| static int | aji_reconnect (struct aji_client *client) |
| static int | aji_recv (struct aji_client *client, int timeout) |
| static void * | aji_recv_loop (void *data) |
| static int | aji_register_approve_handler (void *data, ikspak *pak) |
| static int | aji_register_query_handler (void *data, ikspak *pak) |
| static int | aji_reload (int reload) |
| static int | aji_send_exec (struct ast_channel *chan, const char *data) |
| static int | aji_send_header (struct aji_client *client, const char *to) |
| static int | aji_send_raw (struct aji_client *client, const char *xmlstr) |
| static void | aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc) |
| static char * | aji_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | aji_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | aji_start_sasl (struct aji_client *client, enum ikssasltype type, char *username, char *pass) |
| static int | aji_status_exec (struct ast_channel *chan, const char *data) |
| static char * | aji_test (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| int | ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic) |
| create a chatroom. | |
| int | ast_aji_disconnect (struct aji_client *client) |
| disconnect from jabber server. | |
| struct aji_client * | ast_aji_get_client (const char *name) |
| grab a aji_client structure by label name or JID (without the resource string) | |
| struct aji_client_container * | ast_aji_get_clients (void) |
| void | ast_aji_increment_mid (char *mid) |
| increments the mid field for messages and other events. | |
| int | ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message) |
| invite to a chatroom. | |
| int | ast_aji_join_chat (struct aji_client *client, char *room) |
| join a chatroom. | |
| int | ast_aji_send (struct aji_client *client, iks *x) |
| Wraps raw sending. | |
| int | ast_aji_send_chat (struct aji_client *client, const char *address, const char *message) |
| sends messages. | |
| static int | delete_old_messages (struct aji_client *client, char *from) |
| static int | delete_old_messages_all (struct aji_client *client) |
| static int | gtalk_yuck (iks *node) |
| static iks * | jabber_make_auth (iksid *id, const char *pass, const char *sid) |
| static int | load_module (void) |
| static int | manager_jabber_send (struct mansession *s, const struct message *m) |
| static int | reload (void) |
| static int | unload_module (void) |
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct ast_cli_entry | aji_cli [] |
| static char * | app_ajisend = "JabberSend" |
| static char * | app_ajistatus = "JabberStatus" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct aji_capabilities * | capabilities = NULL |
| static struct aji_client_container | clients |
| static struct ast_flags | globalflags = { AJI_AUTOREGISTER } |
| Global flags, initialized to default values. | |
| static struct ast_custom_function | jabberreceive_function |
| static struct ast_custom_function | jabberstatus_function |
| static ast_cond_t | message_received_condition |
| static ast_mutex_t | messagelock |
References:
Definition in file res_jabber.c.
| #define JABBER_CONFIG "jabber.conf" |
Definition at line 284 of file res_jabber.c.
Referenced by aji_load_config().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 3552 of file res_jabber.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 3552 of file res_jabber.c.
| static int acf_jabberreceive_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 695 of file res_jabber.c.
References aji_client_destroy(), AJI_MAX_JIDLEN, aji_message_destroy(), aji_message::arrived, ast_aji_get_client(), AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_cond_timedwait(), ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvdiff_sec(), ast_tvnow(), ASTOBJ_UNREF, aji_message::from, LOG_NOTICE, LOG_WARNING, aji_message::message, aji_client::message_timeout, aji_client::messages, ast_channel::name, and parse().
00696 { 00697 char *aux = NULL, *parse = NULL; 00698 int timeout; 00699 int jidlen, resourcelen; 00700 struct timeval start; 00701 long diff = 0; 00702 struct aji_client *client = NULL; 00703 int found = 0; 00704 struct aji_message *tmp = NULL; 00705 AST_DECLARE_APP_ARGS(args, 00706 AST_APP_ARG(account); 00707 AST_APP_ARG(jid); 00708 AST_APP_ARG(timeout); 00709 ); 00710 AST_DECLARE_APP_ARGS(jid, 00711 AST_APP_ARG(screenname); 00712 AST_APP_ARG(resource); 00713 ); 00714 00715 if (ast_strlen_zero(data)) { 00716 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00717 return -1; 00718 } 00719 00720 parse = ast_strdupa(data); 00721 AST_STANDARD_APP_ARGS(args, parse); 00722 00723 if (args.argc < 2 || args.argc > 3) { 00724 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00725 return -1; 00726 } 00727 00728 client = ast_aji_get_client(args.account); 00729 if (!client) { 00730 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account); 00731 return -1; 00732 } 00733 00734 parse = ast_strdupa(args.jid); 00735 AST_NONSTANDARD_APP_ARGS(jid, parse, '/'); 00736 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) { 00737 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse); 00738 ASTOBJ_UNREF(client, aji_client_destroy); 00739 return -1; 00740 } 00741 00742 if (ast_strlen_zero(args.timeout)) { 00743 timeout = 20; 00744 } else { 00745 sscanf(args.timeout, "%d", &timeout); 00746 if (timeout <= 0) { 00747 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 00748 ASTOBJ_UNREF(client, aji_client_destroy); 00749 return -1; 00750 } 00751 } 00752 00753 jidlen = strlen(jid.screenname); 00754 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource); 00755 00756 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid); 00757 00758 start = ast_tvnow(); 00759 00760 if (ast_autoservice_start(chan) < 0) { 00761 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", chan->name); 00762 return -1; 00763 } 00764 00765 /* search the messages list, grab the first message that matches with 00766 * the from JID we're expecting, and remove it from the messages list */ 00767 while (diff < timeout) { 00768 struct timespec ts = { 0, }; 00769 struct timeval wait; 00770 int res; 00771 00772 wait = ast_tvadd(start, ast_tv(timeout, 0)); 00773 ts.tv_sec = wait.tv_sec; 00774 ts.tv_nsec = wait.tv_usec * 1000; 00775 00776 /* wait up to timeout seconds for an incoming message */ 00777 ast_mutex_lock(&messagelock); 00778 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts); 00779 ast_mutex_unlock(&messagelock); 00780 if (res == ETIMEDOUT) { 00781 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout); 00782 break; 00783 }; 00784 00785 AST_LIST_LOCK(&client->messages); 00786 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00787 if (jid.argc == 1) { 00788 /* no resource provided, compare bare JIDs */ 00789 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00790 continue; 00791 } 00792 } else { 00793 /* resource appended, compare bare JIDs and resources */ 00794 char *resource = strchr(tmp->from, '/'); 00795 if (!resource || strlen(resource) == 0) { 00796 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from); 00797 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00798 continue; 00799 } 00800 } else { 00801 resource ++; 00802 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) { 00803 continue; 00804 } 00805 } 00806 } 00807 /* check if the message is not too old */ 00808 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00809 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from); 00810 AST_LIST_REMOVE_CURRENT(list); 00811 aji_message_destroy(tmp); 00812 continue; 00813 } 00814 found = 1; 00815 aux = ast_strdupa(tmp->message); 00816 AST_LIST_REMOVE_CURRENT(list); 00817 aji_message_destroy(tmp); 00818 break; 00819 } 00820 AST_LIST_TRAVERSE_SAFE_END; 00821 AST_LIST_UNLOCK(&client->messages); 00822 if (found) { 00823 break; 00824 } 00825 00826 /* check timeout */ 00827 diff = ast_tvdiff_ms(ast_tvnow(), start); 00828 } 00829 00830 ASTOBJ_UNREF(client, aji_client_destroy); 00831 if (ast_autoservice_stop(chan) < 0) { 00832 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", chan->name); 00833 } 00834 00835 /* return if we timed out */ 00836 if (!found) { 00837 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); 00838 return -1; 00839 } 00840 ast_copy_string(buf, aux, buflen); 00841 00842 return 0; 00843 }
| static int acf_jabberstatus_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 629 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.
00630 { 00631 struct aji_client *client = NULL; 00632 struct aji_buddy *buddy = NULL; 00633 struct aji_resource *r = NULL; 00634 int stat = 7; 00635 AST_DECLARE_APP_ARGS(args, 00636 AST_APP_ARG(sender); 00637 AST_APP_ARG(jid); 00638 ); 00639 AST_DECLARE_APP_ARGS(jid, 00640 AST_APP_ARG(screenname); 00641 AST_APP_ARG(resource); 00642 ); 00643 00644 if (!data) { 00645 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00646 return 0; 00647 } 00648 AST_STANDARD_APP_ARGS(args, data); 00649 00650 if (args.argc != 2) { 00651 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00652 return -1; 00653 } 00654 00655 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00656 if (jid.argc < 1 || jid.argc > 2) { 00657 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00658 return -1; 00659 } 00660 00661 if (!(client = ast_aji_get_client(args.sender))) { 00662 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00663 return -1; 00664 } 00665 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00666 if (!buddy) { 00667 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00668 return -1; 00669 } 00670 r = aji_find_resource(buddy, jid.resource); 00671 if (!r && buddy->resources) 00672 r = buddy->resources; 00673 if (!r) 00674 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00675 else 00676 stat = r->status; 00677 snprintf(buf, buflen, "%d", stat); 00678 return 0; 00679 }
| static int aji_act_hook | ( | void * | data, | |
| int | type, | |||
| iks * | node | |||
| ) | [static] |
Definition at line 1329 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(), 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.
01330 { 01331 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01332 ikspak *pak = NULL; 01333 iks *auth = NULL; 01334 int features = 0; 01335 01336 if (!node) { 01337 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 01338 ASTOBJ_UNREF(client, aji_client_destroy); 01339 return IKS_HOOK; 01340 } 01341 01342 if (client->state == AJI_DISCONNECTING) { 01343 ASTOBJ_UNREF(client, aji_client_destroy); 01344 return IKS_HOOK; 01345 } 01346 01347 pak = iks_packet(node); 01348 01349 if (!client->component) { /*client */ 01350 switch (type) { 01351 case IKS_NODE_START: 01352 if (client->usetls && !aji_is_secure(client)) { 01353 #ifndef HAVE_OPENSSL 01354 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"); 01355 ASTOBJ_UNREF(client, aji_client_destroy); 01356 return IKS_HOOK; 01357 #else 01358 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 01359 ast_log(LOG_ERROR, "Could not start TLS\n"); 01360 ASTOBJ_UNREF(client, aji_client_destroy); 01361 return IKS_HOOK; 01362 } 01363 #endif 01364 break; 01365 } 01366 if (!client->usesasl) { 01367 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); 01368 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 01369 if (auth) { 01370 iks_insert_attrib(auth, "id", client->mid); 01371 iks_insert_attrib(auth, "to", client->jid->server); 01372 ast_aji_increment_mid(client->mid); 01373 ast_aji_send(client, auth); 01374 iks_delete(auth); 01375 } else 01376 ast_log(LOG_ERROR, "Out of memory.\n"); 01377 } 01378 break; 01379 01380 case IKS_NODE_NORMAL: 01381 #ifdef HAVE_OPENSSL 01382 if (client->stream_flags & TRY_SECURE) { 01383 if (!strcmp("proceed", iks_name(node))) { 01384 return aji_tls_handshake(client); 01385 } 01386 } 01387 #endif 01388 if (!strcmp("stream:features", iks_name(node))) { 01389 features = iks_stream_features(node); 01390 if (client->usesasl) { 01391 if (client->usetls && !aji_is_secure(client)) 01392 break; 01393 if (client->authorized) { 01394 if (features & IKS_STREAM_BIND) { 01395 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); 01396 auth = iks_make_resource_bind(client->jid); 01397 if (auth) { 01398 iks_insert_attrib(auth, "id", client->mid); 01399 ast_aji_increment_mid(client->mid); 01400 ast_aji_send(client, auth); 01401 iks_delete(auth); 01402 } else { 01403 ast_log(LOG_ERROR, "Out of memory.\n"); 01404 break; 01405 } 01406 } 01407 if (features & IKS_STREAM_SESSION) { 01408 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); 01409 auth = iks_make_session(); 01410 if (auth) { 01411 iks_insert_attrib(auth, "id", "auth"); 01412 ast_aji_increment_mid(client->mid); 01413 ast_aji_send(client, auth); 01414 iks_delete(auth); 01415 } else { 01416 ast_log(LOG_ERROR, "Out of memory.\n"); 01417 } 01418 } 01419 } else { 01420 int ret; 01421 if (!client->jid->user) { 01422 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 01423 break; 01424 } 01425 01426 ret = aji_start_sasl(client, features, client->jid->user, client->password); 01427 if (ret != IKS_OK) { 01428 ASTOBJ_UNREF(client, aji_client_destroy); 01429 return IKS_HOOK; 01430 } 01431 break; 01432 } 01433 } 01434 } else if (!strcmp("failure", iks_name(node))) { 01435 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 01436 } else if (!strcmp("success", iks_name(node))) { 01437 client->authorized = 1; 01438 aji_send_header(client, client->jid->server); 01439 } 01440 break; 01441 case IKS_NODE_ERROR: 01442 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01443 ASTOBJ_UNREF(client, aji_client_destroy); 01444 return IKS_HOOK; 01445 break; 01446 case IKS_NODE_STOP: 01447 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01448 ASTOBJ_UNREF(client, aji_client_destroy); 01449 return IKS_HOOK; 01450 break; 01451 } 01452 } else if (client->state != AJI_CONNECTED && client->component) { 01453 switch (type) { 01454 case IKS_NODE_START: 01455 if (client->state == AJI_DISCONNECTED) { 01456 char secret[160], shasum[320], *handshake; 01457 01458 sprintf(secret, "%s%s", pak->id, client->password); 01459 ast_sha1_hash(shasum, secret); 01460 handshake = NULL; 01461 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01462 aji_send_raw(client, handshake); 01463 ast_free(handshake); 01464 handshake = NULL; 01465 } 01466 client->state = AJI_CONNECTING; 01467 if (aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01468 client->state = AJI_CONNECTED; 01469 else 01470 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01471 break; 01472 } 01473 break; 01474 01475 case IKS_NODE_NORMAL: 01476 break; 01477 01478 case IKS_NODE_ERROR: 01479 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01480 ASTOBJ_UNREF(client, aji_client_destroy); 01481 return IKS_HOOK; 01482 01483 case IKS_NODE_STOP: 01484 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01485 ASTOBJ_UNREF(client, aji_client_destroy); 01486 return IKS_HOOK; 01487 } 01488 } 01489 01490 switch (pak->type) { 01491 case IKS_PAK_NONE: 01492 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01493 break; 01494 case IKS_PAK_MESSAGE: 01495 aji_handle_message(client, pak); 01496 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01497 break; 01498 case IKS_PAK_PRESENCE: 01499 aji_handle_presence(client, pak); 01500 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01501 break; 01502 case IKS_PAK_S10N: 01503 aji_handle_subscribe(client, pak); 01504 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01505 break; 01506 case IKS_PAK_IQ: 01507 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01508 aji_handle_iq(client, node); 01509 break; 01510 default: 01511 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01512 break; 01513 } 01514 01515 iks_filter_packet(client->f, pak); 01516 01517 if (node) 01518 iks_delete(node); 01519 01520 ASTOBJ_UNREF(client, aji_client_destroy); 01521 return IKS_OK; 01522 }
| static void aji_buddy_destroy | ( | struct aji_buddy * | obj | ) | [static] |
Definition at line 384 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().
00385 { 00386 struct aji_resource *tmp; 00387 00388 while ((tmp = obj->resources)) { 00389 obj->resources = obj->resources->next; 00390 ast_free(tmp->description); 00391 ast_free(tmp); 00392 } 00393 00394 ast_free(obj); 00395 }
| static int aji_client_connect | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2746 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().
02747 { 02748 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02749 int res = 0; 02750 02751 if (client) { 02752 if (client->state == AJI_DISCONNECTED) { 02753 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); 02754 client->state = AJI_CONNECTING; 02755 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 02756 iks_filter_remove_hook(client->f, aji_client_connect); 02757 if (!client->component) /*client*/ 02758 aji_get_roster(client); 02759 } 02760 } else 02761 ast_log(LOG_ERROR, "Out of memory.\n"); 02762 02763 ASTOBJ_UNREF(client, aji_client_destroy); 02764 return res; 02765 }
| static void aji_client_destroy | ( | struct aji_client * | obj | ) | [static] |
Definition at line 362 of file res_jabber.c.
References aji_buddy_destroy(), aji_message_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::list, aji_client::messages, aji_client::p, and aji_client::stack.
Referenced by acf_jabberreceive_read(), aji_act_hook(), aji_client_connect(), aji_client_info_handler(), aji_dinfo_handler(), aji_ditems_handler(), aji_log_hook(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), ast_aji_disconnect(), and unload_module().
00363 { 00364 struct aji_message *tmp; 00365 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy); 00366 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00367 iks_filter_delete(obj->f); 00368 iks_parser_delete(obj->p); 00369 iks_stack_delete(obj->stack); 00370 AST_LIST_LOCK(&obj->messages); 00371 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00372 aji_message_destroy(tmp); 00373 } 00374 AST_LIST_HEAD_DESTROY(&obj->messages); 00375 ast_free(obj); 00376 }
| static int aji_client_info_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1743 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.
01744 { 01745 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01746 struct aji_resource *resource = NULL; 01747 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01748 01749 resource = aji_find_resource(buddy, pak->from->resource); 01750 if (pak->subtype == IKS_TYPE_RESULT) { 01751 if (!resource) { 01752 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 01753 ASTOBJ_UNREF(client, aji_client_destroy); 01754 return IKS_FILTER_EAT; 01755 } 01756 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01757 resource->cap->jingle = 1; 01758 } else 01759 resource->cap->jingle = 0; 01760 } else if (pak->subtype == IKS_TYPE_GET) { 01761 iks *iq, *disco, *ident, *google, *query; 01762 iq = iks_new("iq"); 01763 query = iks_new("query"); 01764 ident = iks_new("identity"); 01765 disco = iks_new("feature"); 01766 google = iks_new("feature"); 01767 if (iq && ident && disco && google) { 01768 iks_insert_attrib(iq, "from", client->jid->full); 01769 iks_insert_attrib(iq, "to", pak->from->full); 01770 iks_insert_attrib(iq, "type", "result"); 01771 iks_insert_attrib(iq, "id", pak->id); 01772 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01773 iks_insert_attrib(ident, "category", "client"); 01774 iks_insert_attrib(ident, "type", "pc"); 01775 iks_insert_attrib(ident, "name", "asterisk"); 01776 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 01777 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 01778 iks_insert_node(iq, query); 01779 iks_insert_node(query, ident); 01780 iks_insert_node(query, google); 01781 iks_insert_node(query, disco); 01782 ast_aji_send(client, iq); 01783 } else 01784 ast_log(LOG_ERROR, "Out of Memory.\n"); 01785 01786 iks_delete(iq); 01787 iks_delete(query); 01788 iks_delete(ident); 01789 iks_delete(google); 01790 iks_delete(disco); 01791 } else if (pak->subtype == IKS_TYPE_ERROR) { 01792 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 01793 } 01794 ASTOBJ_UNREF(client, aji_client_destroy); 01795 return IKS_FILTER_EAT; 01796 }
| static int aji_create_buddy | ( | char * | label, | |
| struct aji_client * | client | |||
| ) | [static] |
load config file.
Definition at line 3308 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] |
Definition at line 3087 of file res_jabber.c.
References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_buddy(), AJI_DISCONNECTED, ast_calloc, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::flags, aji_client::forcessl, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, ast_variable::name, aji_client::name, ast_variable::next, aji_client::password, aji_client::port, aji_client::priority, aji_client::serverhost, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and ast_variable::value.
Referenced by aji_load_config().
03088 { 03089 char *resource; 03090 struct aji_client *client = NULL; 03091 int flag = 0; 03092 03093 client = ASTOBJ_CONTAINER_FIND(&clients,label); 03094 if (!client) { 03095 flag = 1; 03096 client = ast_calloc(1, sizeof(*client)); 03097 if (!client) { 03098 ast_log(LOG_ERROR, "Out of memory!\n"); 03099 return 0; 03100 } 03101 ASTOBJ_INIT(client); 03102 ASTOBJ_WRLOCK(client); 03103 ASTOBJ_CONTAINER_INIT(&client->buddies); 03104 } else { 03105 ASTOBJ_WRLOCK(client); 03106 ASTOBJ_UNMARK(client); 03107 } 03108 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 03109 ast_copy_string(client->name, label, sizeof(client->name)); 03110 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 03111 03112 /* Set default values for the client object */ 03113 client->debug = debug; 03114 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 03115 client->port = 5222; 03116 client->usetls = 1; 03117 client->usesasl = 1; 03118 client->forcessl = 0; 03119 client->keepalive = 1; 03120 client->timeout = 50; 03121 client->message_timeout = 5; 03122 AST_LIST_HEAD_INIT(&client->messages); 03123 client->component = 0; 03124 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 03125 client->priority = 0; 03126 client->status = IKS_SHOW_AVAILABLE; 03127 03128 if (flag) { 03129 client->authorized = 0; 03130 client->state = AJI_DISCONNECTED; 03131 } 03132 while (var) { 03133 if (!strcasecmp(var->name, "username")) 03134 ast_copy_string(client->user, var->value, sizeof(client->user)); 03135 else if (!strcasecmp(var->name, "serverhost")) 03136 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 03137 else if (!strcasecmp(var->name, "secret")) 03138 ast_copy_string(client->password, var->value, sizeof(client->password)); 03139 else if (!strcasecmp(var->name, "statusmessage")) 03140 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 03141 else if (!strcasecmp(var->name, "port")) 03142 client->port = atoi(var->value); 03143 else if (!strcasecmp(var->name, "timeout")) 03144 client->message_timeout = atoi(var->value); 03145 else if (!strcasecmp(var->name, "debug")) 03146 client->debug = (ast_false(var->value)) ? 0 : 1; 03147 else if (!strcasecmp(var->name, "type")) { 03148 if (!strcasecmp(var->value, "component")) 03149 client->component = 1; 03150 } else if (!strcasecmp(var->name, "usetls")) { 03151 client->usetls = (ast_false(var->value)) ? 0 : 1; 03152 } else if (!strcasecmp(var->name, "usesasl")) { 03153 client->usesasl = (ast_false(var->value)) ? 0 : 1; 03154 } else if (!strcasecmp(var->name, "forceoldssl")) 03155 client->forcessl = (ast_false(var->value)) ? 0 : 1; 03156 else if (!strcasecmp(var->name, "keepalive")) 03157 client->keepalive = (ast_false(var->value)) ? 0 : 1; 03158 else if (!strcasecmp(var->name, "autoprune")) 03159 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 03160 else if (!strcasecmp(var->name, "autoregister")) 03161 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 03162 else if (!strcasecmp(var->name, "buddy")) 03163 aji_create_buddy((char *)var->value, client); 03164 else if (!strcasecmp(var->name, "priority")) 03165 client->priority = atoi(var->value); 03166 else if (!strcasecmp(var->name, "status")) { 03167 if (!strcasecmp(var->value, "unavailable")) 03168 client->status = IKS_SHOW_UNAVAILABLE; 03169 else 03170 if (!strcasecmp(var->value, "available") 03171 || !strcasecmp(var->value, "online")) 03172 client->status = IKS_SHOW_AVAILABLE; 03173 else 03174 if (!strcasecmp(var->value, "chat") 03175 || !strcasecmp(var->value, "chatty")) 03176 client->status = IKS_SHOW_CHAT; 03177 else 03178 if (!strcasecmp(var->value, "away")) 03179 client->status = IKS_SHOW_AWAY; 03180 else 03181 if (!strcasecmp(var->value, "xa") 03182 || !strcasecmp(var->value, "xaway")) 03183 client->status = IKS_SHOW_XA; 03184 else 03185 if (!strcasecmp(var->value, "dnd")) 03186 client->status = IKS_SHOW_DND; 03187 else 03188 if (!strcasecmp(var->value, "invisible")) 03189 #ifdef IKS_SHOW_INVISIBLE 03190 client->status = IKS_SHOW_INVISIBLE; 03191 #else 03192 { 03193 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 03194 client->status = IKS_SHOW_DND; 03195 } 03196 #endif 03197 else 03198 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 03199 } 03200 /* no transport support in this version */ 03201 /* else if (!strcasecmp(var->name, "transport")) 03202 aji_create_transport(var->value, client); 03203 */ 03204 var = var->next; 03205 } 03206 if (!flag) { 03207 ASTOBJ_UNLOCK(client); 03208 ASTOBJ_UNREF(client, aji_client_destroy); 03209 return 1; 03210 } 03211 03212 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 03213 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 03214 if (!client->p) { 03215 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 03216 return 0; 03217 } 03218 client->stack = iks_stack_new(8192, 8192); 03219 if (!client->stack) { 03220 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 03221 return 0; 03222 } 03223 client->f = iks_filter_new(); 03224 if (!client->f) { 03225 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 03226 return 0; 03227 } 03228 if (!strchr(client->user, '/') && !client->component) { /*client */ 03229 resource = NULL; 03230 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 03231 client->jid = iks_id_new(client->stack, resource); 03232 ast_free(resource); 03233 } 03234 } else 03235 client->jid = iks_id_new(client->stack, client->user); 03236 if (client->component) { 03237 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 03238 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 03239 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); 03240 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); 03241 } else { 03242 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 03243 } 03244 iks_set_log_hook(client->p, aji_log_hook); 03245 ASTOBJ_UNLOCK(client); 03246 ASTOBJ_CONTAINER_LINK(&clients,client); 03247 return 1; 03248 }
| static int aji_dinfo_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1805 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.
01806 { 01807 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01808 char *node = NULL; 01809 struct aji_resource *resource = NULL; 01810 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01811 01812 resource = aji_find_resource(buddy, pak->from->resource); 01813 if (pak->subtype == IKS_TYPE_ERROR) { 01814 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 01815 return IKS_FILTER_EAT; 01816 } 01817 if (pak->subtype == IKS_TYPE_RESULT) { 01818 if (!resource) { 01819 ast_log(LOG_NOTICE,"JABBER: Received client info from %s when not requested.\n", pak->from->full); 01820 ASTOBJ_UNREF(client, aji_client_destroy); 01821 return IKS_FILTER_EAT; 01822 } 01823 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 01824 resource->cap->jingle = 1; 01825 } else 01826 resource->cap->jingle = 0; 01827 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 01828 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 01829 01830 iq = iks_new("iq"); 01831 query = iks_new("query"); 01832 identity = iks_new("identity"); 01833 disco = iks_new("feature"); 01834 reg = iks_new("feature"); 01835 commands = iks_new("feature"); 01836 gateway = iks_new("feature"); 01837 version = iks_new("feature"); 01838 vcard = iks_new("feature"); 01839 search = iks_new("feature"); 01840 01841 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 01842 iks_insert_attrib(iq, "from", client->user); 01843 iks_insert_attrib(iq, "to", pak->from->full); 01844 iks_insert_attrib(iq, "id", pak->id); 01845 iks_insert_attrib(iq, "type", "result"); 01846 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01847 iks_insert_attrib(identity, "category", "gateway"); 01848 iks_insert_attrib(identity, "type", "pstn"); 01849 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 01850 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 01851 iks_insert_attrib(reg, "var", "jabber:iq:register"); 01852 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 01853 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 01854 iks_insert_attrib(version, "var", "jabber:iq:version"); 01855 iks_insert_attrib(vcard, "var", "vcard-temp"); 01856 iks_insert_attrib(search, "var", "jabber:iq:search"); 01857 01858 iks_insert_node(iq, query); 01859 iks_insert_node(query, identity); 01860 iks_insert_node(query, disco); 01861 iks_insert_node(query, reg); 01862 iks_insert_node(query, commands); 01863 iks_insert_node(query, gateway); 01864 iks_insert_node(query, version); 01865 iks_insert_node(query, vcard); 01866 iks_insert_node(query, search); 01867 ast_aji_send(client, iq); 01868 } else { 01869 ast_log(LOG_ERROR, "Out of memory.\n"); 01870 } 01871 01872 iks_delete(iq); 01873 iks_delete(query); 01874 iks_delete(identity); 01875 iks_delete(disco); 01876 iks_delete(reg); 01877 iks_delete(commands); 01878 iks_delete(gateway); 01879 iks_delete(version); 01880 iks_delete(vcard); 01881 iks_delete(search); 01882 01883 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 01884 iks *iq, *query, *confirm; 01885 iq = iks_new("iq"); 01886 query = iks_new("query"); 01887 confirm = iks_new("item"); 01888 01889 if (iq && query && confirm && client) { 01890 iks_insert_attrib(iq, "from", client->user); 01891 iks_insert_attrib(iq, "to", pak->from->full); 01892 iks_insert_attrib(iq, "id", pak->id); 01893 iks_insert_attrib(iq, "type", "result"); 01894 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01895 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01896 iks_insert_attrib(confirm, "node", "confirmaccount"); 01897 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01898 iks_insert_attrib(confirm, "jid", client->user); 01899 iks_insert_node(iq, query); 01900 iks_insert_node(query, confirm); 01901 ast_aji_send(client, iq); 01902 } else { 01903 ast_log(LOG_ERROR, "Out of memory.\n"); 01904 } 01905 01906 iks_delete(iq); 01907 iks_delete(query); 01908 iks_delete(confirm); 01909 01910 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 01911 iks *iq, *query, *feature; 01912 01913 iq = iks_new("iq"); 01914 query = iks_new("query"); 01915 feature = iks_new("feature"); 01916 01917 if (iq && query && feature && client) { 01918 iks_insert_attrib(iq, "from", client->user); 01919 iks_insert_attrib(iq, "to", pak->from->full); 01920 iks_insert_attrib(iq, "id", pak->id); 01921 iks_insert_attrib(iq, "type", "result"); 01922 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 01923 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01924 iks_insert_node(iq, query); 01925 iks_insert_node(query, feature); 01926 ast_aji_send(client, iq); 01927 } else { 01928 ast_log(LOG_ERROR, "Out of memory.\n"); 01929 } 01930 01931 iks_delete(iq); 01932 iks_delete(query); 01933 iks_delete(feature); 01934 } 01935 01936 ASTOBJ_UNREF(client, aji_client_destroy); 01937 return IKS_FILTER_EAT; 01938 }
| static int aji_ditems_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1646 of file res_jabber.c.
References aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, and aji_client::user.
01647 { 01648 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01649 char *node = NULL; 01650 01651 if (!(node = iks_find_attrib(pak->query, "node"))) { 01652 iks *iq = NULL, *query = NULL, *item = NULL; 01653 iq = iks_new("iq"); 01654 query = iks_new("query"); 01655 item = iks_new("item"); 01656 01657 if (iq && query && item) { 01658 iks_insert_attrib(iq, "from", client->user); 01659 iks_insert_attrib(iq, "to", pak->from->full); 01660 iks_insert_attrib(iq, "id", pak->id); 01661 iks_insert_attrib(iq, "type", "result"); 01662 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01663 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01664 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01665 iks_insert_attrib(item, "jid", client->user); 01666 01667 iks_insert_node(iq, query); 01668 iks_insert_node(query, item); 01669 ast_aji_send(client, iq); 01670 } else { 01671 ast_log(LOG_ERROR, "Out of memory.\n"); 01672 } 01673 01674 iks_delete(iq); 01675 iks_delete(query); 01676 iks_delete(item); 01677 01678 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01679 iks *iq, *query, *confirm; 01680 iq = iks_new("iq"); 01681 query = iks_new("query"); 01682 confirm = iks_new("item"); 01683 if (iq && query && confirm && client) { 01684 iks_insert_attrib(iq, "from", client->user); 01685 iks_insert_attrib(iq, "to", pak->from->full); 01686 iks_insert_attrib(iq, "id", pak->id); 01687 iks_insert_attrib(iq, "type", "result"); 01688 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01689 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01690 iks_insert_attrib(confirm, "node", "confirmaccount"); 01691 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01692 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01693 01694 iks_insert_node(iq, query); 01695 iks_insert_node(query, confirm); 01696 ast_aji_send(client, iq); 01697 } else { 01698 ast_log(LOG_ERROR, "Out of memory.\n"); 01699 } 01700 01701 iks_delete(iq); 01702 iks_delete(query); 01703 iks_delete(confirm); 01704 01705 } else if (!strcasecmp(node, "confirmaccount")) { 01706 iks *iq = NULL, *query = NULL, *feature = NULL; 01707 01708 iq = iks_new("iq"); 01709 query = iks_new("query"); 01710 feature = iks_new("feature"); 01711 01712 if (iq && query && feature && client) { 01713 iks_insert_attrib(iq, "from", client->user); 01714 iks_insert_attrib(iq, "to", pak->from->full); 01715 iks_insert_attrib(iq, "id", pak->id); 01716 iks_insert_attrib(iq, "type", "result"); 01717 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01718 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01719 iks_insert_node(iq, query); 01720 iks_insert_node(query, feature); 01721 ast_aji_send(client, iq); 01722 } else { 01723 ast_log(LOG_ERROR, "Out of memory.\n"); 01724 } 01725 01726 iks_delete(iq); 01727 iks_delete(query); 01728 iks_delete(feature); 01729 } 01730 01731 ASTOBJ_UNREF(client, aji_client_destroy); 01732 return IKS_FILTER_EAT; 01733 01734 }
| static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2905 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.
02906 { 02907 switch (cmd) { 02908 case CLI_INIT: 02909 e->command = "jabber reload"; 02910 e->usage = 02911 "Usage: jabber reload\n" 02912 " Reloads the Jabber module.\n"; 02913 return NULL; 02914 case CLI_GENERATE: 02915 return NULL; 02916 } 02917 02918 aji_reload(1); 02919 ast_cli(a->fd, "Jabber Reloaded.\n"); 02920 return CLI_SUCCESS; 02921 }
| static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2864 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.
02865 { 02866 switch (cmd) { 02867 case CLI_INIT: 02868 e->command = "jabber set debug {on|off}"; 02869 e->usage = 02870 "Usage: jabber set debug {on|off}\n" 02871 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 02872 return NULL; 02873 case CLI_GENERATE: 02874 return NULL; 02875 } 02876 02877 if (a->argc != e->args) 02878 return CLI_SHOWUSAGE; 02879 02880 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 02881 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02882 ASTOBJ_RDLOCK(iterator); 02883 iterator->debug = 1; 02884 ASTOBJ_UNLOCK(iterator); 02885 }); 02886 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 02887 return CLI_SUCCESS; 02888 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 02889 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02890 ASTOBJ_RDLOCK(iterator); 02891 iterator->debug = 0; 02892 ASTOBJ_UNLOCK(iterator); 02893 }); 02894 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 02895 return CLI_SUCCESS; 02896 } 02897 return CLI_SHOWUSAGE; /* defaults to invalid */ 02898 }
| static int aji_filter_roster | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2616 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().
02617 { 02618 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02619 int flag = 0; 02620 iks *x = NULL; 02621 struct aji_buddy *buddy; 02622 02623 client->state = AJI_CONNECTED; 02624 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02625 ASTOBJ_RDLOCK(iterator); 02626 x = iks_child(pak->query); 02627 flag = 0; 02628 while (x) { 02629 if (!iks_strcmp(iks_name(x), "item")) { 02630 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02631 flag = 1; 02632 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02633 } 02634 } 02635 x = iks_next(x); 02636 } 02637 if (!flag) 02638 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02639 iks_delete(x); 02640 02641 ASTOBJ_UNLOCK(iterator); 02642 }); 02643 02644 x = iks_child(pak->query); 02645 while (x) { 02646 flag = 0; 02647 if (iks_strcmp(iks_name(x), "item") == 0) { 02648 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02649 ASTOBJ_RDLOCK(iterator); 02650 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02651 flag = 1; 02652 ASTOBJ_UNLOCK(iterator); 02653 }); 02654 02655 if (flag) { 02656 /* found buddy, don't create a new one */ 02657 x = iks_next(x); 02658 continue; 02659 } 02660 02661 buddy = ast_calloc(1, sizeof(*buddy)); 02662 if (!buddy) { 02663 ast_log(LOG_WARNING, "Out of memory\n"); 02664 return 0; 02665 } 02666 ASTOBJ_INIT(buddy); 02667 ASTOBJ_WRLOCK(buddy); 02668 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02669 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02670 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02671 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 02672 ASTOBJ_MARK(buddy); 02673 } else if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 02674 /* subscribe to buddy's presence only 02675 if we really need to */ 02676 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 02677 } 02678 ASTOBJ_UNLOCK(buddy); 02679 if (buddy) { 02680 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 02681 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02682 } 02683 } 02684 x = iks_next(x); 02685 } 02686 02687 iks_delete(x); 02688 aji_pruneregister(client); 02689 02690 ASTOBJ_UNREF(client, aji_client_destroy); 02691 return IKS_FILTER_EAT; 02692 }
| static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
| char * | name | |||
| ) | [static, read] |
Definition at line 493 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().
00494 { 00495 struct aji_resource *res = NULL; 00496 if (!buddy || !name) 00497 return res; 00498 res = buddy->resources; 00499 while (res) { 00500 if (!strcasecmp(res->resource, name)) { 00501 break; 00502 } 00503 res = res->next; 00504 } 00505 return res; 00506 }
| static struct aji_version* aji_find_version | ( | char * | node, | |
| char * | version, | |||
| ikspak * | pak | |||
| ) | [static, read] |
Definition at line 424 of file res_jabber.c.
References ast_copy_string(), ast_free, ast_log(), ast_malloc, aji_version::jingle, LOG_ERROR, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::parent, aji_version::version, and aji_capabilities::versions.
Referenced by aji_handle_presence().
00425 { 00426 struct aji_capabilities *list = NULL; 00427 struct aji_version *res = NULL; 00428 00429 list = capabilities; 00430 00431 if (!node) 00432 node = pak->from->full; 00433 if (!version) 00434 version = "none supplied."; 00435 while(list) { 00436 if (!strcasecmp(list->node, node)) { 00437 res = list->versions; 00438 while(res) { 00439 if (!strcasecmp(res->version, version)) 00440 return res; 00441 res = res->next; 00442 } 00443 /* Specified version not found. Let's add it to 00444 this node in our capabilities list */ 00445 if (!res) { 00446 res = ast_malloc(sizeof(*res)); 00447 if (!res) { 00448 ast_log(LOG_ERROR, "Out of memory!\n"); 00449 return NULL; 00450 } 00451 res->jingle = 0; 00452 res->parent = list; 00453 ast_copy_string(res->version, version, sizeof(res->version)); 00454 res->next = list->versions; 00455 list->versions = res; 00456 return res; 00457 } 00458 } 00459 list = list->next; 00460 } 00461 /* Specified node not found. Let's add it our capabilities list */ 00462 if (!list) { 00463 list = ast_malloc(sizeof(*list)); 00464 if (!list) { 00465 ast_log(LOG_ERROR, "Out of memory!\n"); 00466 return NULL; 00467 } 00468 res = ast_malloc(sizeof(*res)); 00469 if (!res) { 00470 ast_log(LOG_ERROR, "Out of memory!\n"); 00471 ast_free(list); 00472 return NULL; 00473 } 00474 ast_copy_string(list->node, node, sizeof(list->node)); 00475 ast_copy_string(res->version, version, sizeof(res->version)); 00476 res->jingle = 0; 00477 res->parent = list; 00478 res->next = NULL; 00479 list->versions = res; 00480 list->next = capabilities; 00481 capabilities = list; 00482 } 00483 return res; 00484 }
| static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Definition at line 2723 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().
02724 { 02725 iks *roster = NULL; 02726 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 02727 02728 if (roster) { 02729 iks_insert_attrib(roster, "id", "roster"); 02730 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 02731 ast_aji_send(client, roster); 02732 } 02733 02734 iks_delete(roster); 02735 02736 return 1; 02737 }
| static void aji_handle_iq | ( | struct aji_client * | client, | |
| iks * | node | |||
| ) | [static] |
| static void aji_handle_message | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1959 of file res_jabber.c.
References aji_message::arrived, ast_calloc, ast_cond_broadcast(), ast_copy_string(), ast_debug, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, ast_tvnow(), delete_old_messages(), aji_message::from, aji_message::id, aji_message::list, LOG_ERROR, aji_message::message, aji_client::messages, and aji_client::name.
Referenced by aji_act_hook().
01960 { 01961 struct aji_message *insert; 01962 int deleted = 0; 01963 01964 ast_debug(3, "client %s received a message\n", client->name); 01965 01966 if (!(insert = ast_calloc(1, sizeof(*insert)))) { 01967 return; 01968 } 01969 01970 insert->arrived = ast_tvnow(); 01971 01972 /* wake up threads waiting for messages */ 01973 ast_mutex_lock(&messagelock); 01974 ast_cond_broadcast(&message_received_condition); 01975 ast_mutex_unlock(&messagelock); 01976 01977 if (iks_find_cdata(pak->x, "body")) { 01978 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 01979 } 01980 if (pak->id) { 01981 ast_copy_string(insert->id, pak->id, sizeof(insert->id)); 01982 } 01983 if (pak->from){ 01984 /* insert will furtherly be added to message list */ 01985 insert->from = ast_strdup(pak->from->full); 01986 if (!insert->from) { 01987 ast_log(LOG_ERROR, "Memory allocation failure\n"); 01988 return; 01989 } 01990 ast_debug(3, "message comes from %s\n", insert->from); 01991 } 01992 01993 /* remove old messages received from this JID 01994 * and insert received message */ 01995 deleted = delete_old_messages(client, pak->from->partial); 01996 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 01997 AST_LIST_LOCK(&client->messages); 01998 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 01999 AST_LIST_UNLOCK(&client->messages); 02000 }
| static void aji_handle_presence | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2008 of file res_jabber.c.
References aji_buddy_destroy(), AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_strdup, ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, descrip, aji_resource::description, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, aji_client::mid, aji_resource::next, option_debug, aji_resource::priority, aji_resource::resource, aji_buddy::resources, aji_client::state, aji_resource::status, aji_client::status, status, aji_client::statusmessage, type, and ver.
Referenced by aji_act_hook().
02009 { 02010 int status, priority; 02011 struct aji_buddy *buddy; 02012 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02013 char *ver, *node, *descrip, *type; 02014 02015 if (client->state != AJI_CONNECTED) 02016 aji_create_buddy(pak->from->partial, client); 02017 02018 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02019 if (!buddy && pak->from->partial) { 02020 /* allow our jid to be used to log in with another resource */ 02021 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02022 aji_create_buddy(pak->from->partial, client); 02023 else 02024 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02025 return; 02026 } 02027 type = iks_find_attrib(pak->x, "type"); 02028 if (client->component && type &&!strcasecmp("probe", type)) { 02029 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02030 ast_verbose("what i was looking for \n"); 02031 } 02032 ASTOBJ_WRLOCK(buddy); 02033 status = (pak->show) ? pak->show : 6; 02034 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02035 tmp = buddy->resources; 02036 descrip = ast_strdup(iks_find_cdata(pak->x,"status")); 02037 02038 while (tmp && pak->from->resource) { 02039 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02040 tmp->status = status; 02041 if (tmp->description) ast_free(tmp->description); 02042 tmp->description = descrip; 02043 found = tmp; 02044 if (status == 6) { /* Sign off Destroy resource */ 02045 if (last && found->next) { 02046 last->next = found->next; 02047 } else if (!last) { 02048 if (found->next) 02049 buddy->resources = found->next; 02050 else 02051 buddy->resources = NULL; 02052 } else if (!found->next) { 02053 if (last) 02054 last->next = NULL; 02055 else 02056 buddy->resources = NULL; 02057 } 02058 ast_free(found); 02059 found = NULL; 02060 break; 02061 } 02062 /* resource list is sorted by descending priority */ 02063 if (tmp->priority != priority) { 02064 found->priority = priority; 02065 if (!last && !found->next) 02066 /* resource was found to be unique, 02067 leave loop */ 02068 break; 02069 /* search for resource in our list 02070 and take it out for the moment */ 02071 if (last) 02072 last->next = found->next; 02073 else 02074 buddy->resources = found->next; 02075 02076 last = NULL; 02077 tmp = buddy->resources; 02078 if (!buddy->resources) 02079 buddy->resources = found; 02080 /* priority processing */ 02081 while (tmp) { 02082 /* insert resource back according to 02083 its priority value */ 02084 if (found->priority > tmp->priority) { 02085 if (last) 02086 /* insert within list */ 02087 last->next = found; 02088 found->next = tmp; 02089 if (!last) 02090 /* insert on top */ 02091 buddy->resources = found; 02092 break; 02093 } 02094 if (!tmp->next) { 02095 /* insert at the end of the list */ 02096 tmp->next = found; 02097 found->next = NULL; 02098 break; 02099 } 02100 last = tmp; 02101 tmp = tmp->next; 02102 } 02103 } 02104 break; 02105 } 02106 last = tmp; 02107 tmp = tmp->next; 02108 } 02109 02110 /* resource not found in our list, create it */ 02111 if (!found && status != 6 && pak->from->resource) { 02112 found = ast_calloc(1, sizeof(*found)); 02113 02114 if (!found) { 02115 ast_log(LOG_ERROR, "Out of memory!\n"); 02116 return; 02117 } 02118 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02119 found->status = status; 02120 found->description = descrip; 02121 found->priority = priority; 02122 found->next = NULL; 02123 last = NULL; 02124 tmp = buddy->resources; 02125 while (tmp) { 02126 if (found->priority > tmp->priority) { 02127 if (last) 02128 last->next = found; 02129 found->next = tmp; 02130 if (!last) 02131 buddy->resources = found; 02132 break; 02133 } 02134 if (!tmp->next) { 02135 tmp->next = found; 02136 break; 02137 } 02138 last = tmp; 02139 tmp = tmp->next; 02140 } 02141 if (!tmp) 02142 buddy->resources = found; 02143 } 02144 02145 ASTOBJ_UNLOCK(buddy); 02146 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02147 02148 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02149 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02150 02151 /* handle gmail client's special caps:c tag */ 02152 if (!node && !ver) { 02153 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02154 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02155 } 02156 02157 /* retrieve capabilites of the new resource */ 02158 if (status != 6 && found && !found->cap) { 02159 found->cap = aji_find_version(node, ver, pak); 02160 if (gtalk_yuck(pak->x)) /* gtalk should do discover */ 02161 found->cap->jingle = 1; 02162 if (found->cap->jingle && option_debug > 4) { 02163 ast_debug(1,"Special case for google till they support discover.\n"); 02164 } 02165 else { 02166 iks *iq, *query; 02167 iq = iks_new("iq"); 02168 query = iks_new("query"); 02169 if (query && iq) { 02170 iks_insert_attrib(iq, "type", "get"); 02171 iks_insert_attrib(iq, "to", pak->from->full); 02172 iks_insert_attrib(iq,"from", client->jid->full); 02173 iks_insert_attrib(iq, "id", client->mid); 02174 ast_aji_increment_mid(client->mid); 02175 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02176 iks_insert_node(iq, query); 02177 ast_aji_send(client, iq); 02178 02179 } else 02180 ast_log(LOG_ERROR, "Out of memory.\n"); 02181 02182 iks_delete(query); 02183 iks_delete(iq); 02184 } 02185 } 02186 switch (pak->subtype) { 02187 case IKS_TYPE_AVAILABLE: 02188 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 02189 break; 02190 case IKS_TYPE_UNAVAILABLE: 02191 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 02192 break; 02193 default: 02194 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 02195 } 02196 switch (pak->show) { 02197 case IKS_SHOW_UNAVAILABLE: 02198 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02199 break; 02200 case IKS_SHOW_AVAILABLE: 02201 ast_debug(3, "JABBER: type is available\n"); 02202 break; 02203 case IKS_SHOW_CHAT: 02204 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02205 break; 02206 case IKS_SHOW_AWAY: 02207 ast_debug(3, "JABBER: type is away\n"); 02208 break; 02209 case IKS_SHOW_XA: 02210 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02211 break; 02212 case IKS_SHOW_DND: 02213 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02214 break; 02215 default: 02216 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 02217 } 02218 }
| static void aji_handle_subscribe | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2227 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().
02228 { 02229 iks *presence = NULL, *status = NULL; 02230 struct aji_buddy* buddy = NULL; 02231 02232 switch (pak->subtype) { 02233 case IKS_TYPE_SUBSCRIBE: 02234 presence = iks_new("presence"); 02235 status = iks_new("status"); 02236 if (presence && status) { 02237 iks_insert_attrib(presence, "type", "subscribed"); 02238 iks_insert_attrib(presence, "to", pak->from->full); 02239 iks_insert_attrib(presence, "from", client->jid->full); 02240 if (pak->id) 02241 iks_insert_attrib(presence, "id", pak->id); 02242 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02243 iks_insert_node(presence, status); 02244 ast_aji_send(client, presence); 02245 } else 02246 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02247 02248 iks_delete(presence); 02249 iks_delete(status); 02250 02251 if (client->component) 02252 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02253 case IKS_TYPE_SUBSCRIBED: 02254 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02255 if (!buddy && pak->from->partial) { 02256 aji_create_buddy(pak->from->partial, client); 02257 } 02258 default: 02259 if (option_verbose > 4) { 02260 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 02261 } 02262 } 02263 }
| static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 2773 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().
02774 { 02775 int connected = IKS_NET_NOCONN; 02776 02777 #ifdef HAVE_OPENSSL 02778 /* reset stream flags */ 02779 client->stream_flags = 0; 02780 #endif 02781 /* If it's a component, connect to user, otherwise, connect to server */ 02782 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 02783 02784 if (connected == IKS_NET_NOCONN) { 02785 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 02786 return IKS_HOOK; 02787 } else if (connected == IKS_NET_NODNS) { 02788 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, S_OR(client->serverhost, client->jid->server)); 02789 return IKS_HOOK; 02790 } 02791 02792 return IKS_OK; 02793 }
| static int aji_io_recv | ( | struct aji_client * | client, | |
| char * | buffer, | |||
| size_t | buf_len, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 1046 of file res_jabber.c.
References aji_is_secure(), ast_select(), len(), and aji_client::p.
Referenced by aji_recv().
01047 { 01048 int sock; 01049 fd_set fds; 01050 struct timeval tv, *tvptr = NULL; 01051 int len, res; 01052 01053 #ifdef HAVE_OPENSSL 01054 if (aji_is_secure(client)) { 01055 sock = SSL_get_fd(client->ssl_session); 01056 if (sock < 0) 01057 return -1; 01058 } else 01059 #endif /* HAVE_OPENSSL */ 01060 sock = iks_fd(client->p); 01061 01062 memset(&tv, 0, sizeof(struct timeval)); 01063 FD_ZERO(&fds); 01064 FD_SET(sock, &fds); 01065 tv.tv_sec = timeout; 01066 01067 /* NULL value for tvptr makes ast_select wait indefinitely */ 01068 tvptr = (timeout != -1) ? &tv : NULL; 01069 01070 /* ast_select emulates linux behaviour in terms of timeout handling */ 01071 res = ast_select(sock + 1, &fds, NULL, NULL, tvptr); 01072 if (res > 0) { 01073 #ifdef HAVE_OPENSSL 01074 if (aji_is_secure(client)) { 01075 len = SSL_read(client->ssl_session, buffer, buf_len); 01076 } else 01077 #endif /* HAVE_OPENSSL */ 01078 len = recv(sock, buffer, buf_len, 0); 01079 01080 if (len > 0) { 01081 return len; 01082 } else if (len <= 0) { 01083 return -1; 01084 } 01085 } 01086 return res; 01087 }
| static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Definition at line 956 of file res_jabber.c.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
00957 { 00958 #ifdef HAVE_OPENSSL 00959 return client->stream_flags & SECURE; 00960 #else 00961 return 0; 00962 #endif 00963 }
| static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 3335 of file res_jabber.c.
References AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, debug, JABBER_CONFIG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by aji_reload().
03336 { 03337 char *cat = NULL; 03338 int debug = 1; 03339 struct ast_config *cfg = NULL; 03340 struct ast_variable *var = NULL; 03341 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 03342 03343 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 03344 return -1; 03345 03346 /* Reset flags to default value */ 03347 ast_set_flag(&globalflags, AJI_AUTOREGISTER); 03348 03349 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 03350 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 03351 return 0; 03352 } 03353 03354 cat = ast_category_browse(cfg, NULL); 03355 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 03356 if (!strcasecmp(var->name, "debug")) { 03357 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 03358 } else if (!strcasecmp(var->name, "autoprune")) { 03359 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 03360 } else if (!strcasecmp(var->name, "autoregister")) { 03361 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 03362 } 03363 } 03364 03365 while (cat) { 03366 if (strcasecmp(cat, "general")) { 03367 var = ast_variable_browse(cfg, cat); 03368 aji_create_client(cat, var, debug); 03369 } 03370 cat = ast_category_browse(cfg, cat); 03371 } 03372 ast_config_destroy(cfg); /* or leak memory */ 03373 return 1; 03374 }
| static void aji_log_hook | ( | void * | data, | |
| const char * | xmpp, | |||
| size_t | size, | |||
| int | is_incoming | |||
| ) | [static] |
Definition at line 1246 of file res_jabber.c.
References aji_client_destroy(), ast_strlen_zero(), ast_verbose, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::debug, EVENT_FLAG_USER, manager_event, aji_client::name, and option_debug.
Referenced by aji_recv(), and aji_send_raw().
01247 { 01248 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01249 01250 if (!ast_strlen_zero(xmpp)) 01251 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 01252 01253 if (client->debug) { 01254 if (is_incoming) 01255 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 01256 else { 01257 if (strlen(xmpp) == 1) { 01258 if (option_debug > 2 && xmpp[0] == ' ') { 01259 ast_verbose("\nJABBER: Keep alive packet\n"); 01260 } 01261 } else 01262 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 01263 } 01264 01265 } 01266 ASTOBJ_UNREF(client, aji_client_destroy); 01267 }
| static void aji_message_destroy | ( | struct aji_message * | obj | ) | [static] |
Definition at line 403 of file res_jabber.c.
References ast_free, aji_message::from, and aji_message::message.
Referenced by acf_jabberreceive_read(), aji_client_destroy(), and delete_old_messages().
00404 { 00405 if (obj->from) { 00406 ast_free(obj->from); 00407 } 00408 if (obj->message) { 00409 ast_free(obj->message); 00410 } 00411 ast_free(obj); 00412 }
| static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2561 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.
02562 { 02563 int res = 0; 02564 iks *removeiq = iks_new("iq"); 02565 iks *removequery = iks_new("query"); 02566 iks *removeitem = iks_new("item"); 02567 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02568 if (!client || !removeiq || !removequery || !removeitem || !send) { 02569 ast_log(LOG_ERROR, "Out of memory.\n"); 02570 goto safeout; 02571 } 02572 02573 iks_insert_node(removeiq, removequery); 02574 iks_insert_node(removequery, removeitem); 02575 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02576 ASTOBJ_RDLOCK(iterator); 02577 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02578 * be called at the same time */ 02579 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02580 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02581 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02582 " so I am no longer subscribing to your presence.\n")); 02583 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02584 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02585 " your access to my presence.\n")); 02586 iks_insert_attrib(removeiq, "from", client->jid->full); 02587 iks_insert_attrib(removeiq, "type", "set"); 02588 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02589 iks_insert_attrib(removeitem, "jid", iterator->name); 02590 iks_insert_attrib(removeitem, "subscription", "remove"); 02591 res = ast_aji_send(client, removeiq); 02592 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02593 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02594 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02595 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02596 } 02597 ASTOBJ_UNLOCK(iterator); 02598 }); 02599 02600 safeout: 02601 iks_delete(removeiq); 02602 iks_delete(removequery); 02603 iks_delete(removeitem); 02604 iks_delete(send); 02605 02606 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); 02607 }
| static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 2700 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().
02701 { 02702 int res = 0; 02703 02704 if (client->state) 02705 client->state = AJI_DISCONNECTED; 02706 client->timeout=50; 02707 if (client->p) 02708 iks_parser_reset(client->p); 02709 if (client->authorized) 02710 client->authorized = 0; 02711 02712 res = aji_initialize(client); 02713 02714 return res; 02715 }
| static int aji_recv | ( | struct aji_client * | client, | |
| int | timeout | |||
| ) | [static] |
Definition at line 1101 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().
01102 { 01103 int len, ret; 01104 char buf[NET_IO_BUF_SIZE - 1]; 01105 char newbuf[NET_IO_BUF_SIZE - 1]; 01106 int pos = 0; 01107 int newbufpos = 0; 01108 unsigned char c; 01109 01110 memset(buf, 0, sizeof(buf)); 01111 memset(newbuf, 0, sizeof(newbuf)); 01112 01113 while (1) { 01114 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 01115 if (len < 0) return IKS_NET_RWERR; 01116 if (len == 0) return IKS_NET_EXPIRED; 01117 buf[len] = '\0'; 01118 01119 /* our iksemel parser won't work as expected if we feed 01120 it with XML packets that contain multiple whitespace 01121 characters between tags */ 01122 while (pos < len) { 01123 c = buf[pos]; 01124 /* if we stumble on the ending tag character, 01125 we skip any whitespace that follows it*/ 01126 if (c == '>') { 01127 while (isspace(buf[pos+1])) { 01128 pos++; 01129 } 01130 } 01131 newbuf[newbufpos] = c; 01132 newbufpos ++; 01133 pos++; 01134 } 01135 pos = 0; 01136 newbufpos = 0; 01137 01138 /* Log the message here, because iksemel's logHook is 01139 unaccessible */ 01140 aji_log_hook(client, buf, len, 1); 01141 01142 /* let iksemel deal with the string length, 01143 and reset our buffer */ 01144 ret = iks_parse(client->p, newbuf, 0, 0); 01145 memset(newbuf, 0, sizeof(newbuf)); 01146 01147 switch (ret) { 01148 case IKS_NOMEM: 01149 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 01150 break; 01151 case IKS_BADXML: 01152 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 01153 break; 01154 case IKS_HOOK: 01155 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 01156 break; 01157 } 01158 if (ret != IKS_OK) { 01159 return ret; 01160 } 01161 ast_debug(3, "XML parsing successful\n"); 01162 } 01163 return IKS_OK; 01164 }
| static void * aji_recv_loop | ( | void * | data | ) | [static] |
Definition at line 2395 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, delete_old_messages_all(), IKS_NET_EXPIRED, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::state, and aji_client::timeout.
Referenced by aji_reload().
02396 { 02397 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02398 int res = IKS_HOOK; 02399 02400 while(res != IKS_OK) { 02401 ast_debug(3, "JABBER: Connecting.\n"); 02402 res = aji_reconnect(client); 02403 sleep(4); 02404 } 02405 02406 do { 02407 if (res == IKS_NET_RWERR || client->timeout == 0) { 02408 while(res != IKS_OK) { 02409 ast_debug(3, "JABBER: reconnecting.\n"); 02410 res = aji_reconnect(client); 02411 sleep(4); 02412 } 02413 } 02414 02415 res = aji_recv(client, 1); 02416 02417 if (client->state == AJI_DISCONNECTING) { 02418 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02419 pthread_exit(NULL); 02420 } 02421 02422 /* Decrease timeout if no data received, and delete 02423 * old messages globally */ 02424 if (res == IKS_NET_EXPIRED) { 02425 client->timeout--; 02426 delete_old_messages_all(client); 02427 } 02428 if (res == IKS_HOOK) { 02429 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02430 } else if (res == IKS_NET_TLSFAIL) { 02431 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02432 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02433 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02434 if (res == IKS_OK) { 02435 client->timeout = 50; 02436 } else { 02437 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02438 } 02439 } else if (res == IKS_NET_RWERR) { 02440 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02441 } 02442 } while (client); 02443 ASTOBJ_UNREF(client, aji_client_destroy); 02444 return 0; 02445 }
| static int aji_register_approve_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1530 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.
01531 { 01532 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01533 iks *iq = NULL, *presence = NULL, *x = NULL; 01534 01535 iq = iks_new("iq"); 01536 presence = iks_new("presence"); 01537 x = iks_new("x"); 01538 if (client && iq && presence && x) { 01539 if (!iks_find(pak->query, "remove")) { 01540 iks_insert_attrib(iq, "from", client->jid->full); 01541 iks_insert_attrib(iq, "to", pak->from->full); 01542 iks_insert_attrib(iq, "id", pak->id); 01543 iks_insert_attrib(iq, "type", "result"); 01544 ast_aji_send(client, iq); 01545 01546 iks_insert_attrib(presence, "from", client->jid->full); 01547 iks_insert_attrib(presence, "to", pak->from->partial); 01548 iks_insert_attrib(presence, "id", client->mid); 01549 ast_aji_increment_mid(client->mid); 01550 iks_insert_attrib(presence, "type", "subscribe"); 01551 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01552 iks_insert_node(presence, x); 01553 ast_aji_send(client, presence); 01554 } 01555 } else { 01556 ast_log(LOG_ERROR, "Out of memory.\n"); 01557 } 01558 01559 01560 iks_delete(iq); 01561 iks_delete(presence); 01562 iks_delete(x); 01563 01564 ASTOBJ_UNREF(client, aji_client_destroy); 01565 return IKS_FILTER_EAT; 01566 }
| static int aji_register_query_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1574 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.
01575 { 01576 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01577 struct aji_buddy *buddy = NULL; 01578 char *node = NULL; 01579 iks *iq = NULL, *query = NULL; 01580 01581 client = (struct aji_client *) data; 01582 01583 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01584 if (!buddy) { 01585 iks *error = NULL, *notacceptable = NULL; 01586 01587 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01588 iq = iks_new("iq"); 01589 query = iks_new("query"); 01590 error = iks_new("error"); 01591 notacceptable = iks_new("not-acceptable"); 01592 if (iq && query && error && notacceptable) { 01593 iks_insert_attrib(iq, "type", "error"); 01594 iks_insert_attrib(iq, "from", client->user); 01595 iks_insert_attrib(iq, "to", pak->from->full); 01596 iks_insert_attrib(iq, "id", pak->id); 01597 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01598 iks_insert_attrib(error, "code" , "406"); 01599 iks_insert_attrib(error, "type", "modify"); 01600 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01601 iks_insert_node(iq, query); 01602 iks_insert_node(iq, error); 01603 iks_insert_node(error, notacceptable); 01604 ast_aji_send(client, iq); 01605 } else { 01606 ast_log(LOG_ERROR, "Out of memory.\n"); 01607 } 01608 01609 iks_delete(error); 01610 iks_delete(notacceptable); 01611 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01612 iks *instructions = NULL; 01613 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01614 iq = iks_new("iq"); 01615 query = iks_new("query"); 01616 instructions = iks_new("instructions"); 01617 if (iq && query && instructions && client) { 01618 iks_insert_attrib(iq, "from", client->user); 01619 iks_insert_attrib(iq, "to", pak->from->full); 01620 iks_insert_attrib(iq, "id", pak->id); 01621 iks_insert_attrib(iq, "type", "result"); 01622 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01623 iks_insert_cdata(instructions, explain, 0); 01624 iks_insert_node(iq, query); 01625 iks_insert_node(query, instructions); 01626 ast_aji_send(client, iq); 01627 } else { 01628 ast_log(LOG_ERROR, "Out of memory.\n"); 01629 } 01630 01631 iks_delete(instructions); 01632 } 01633 iks_delete(iq); 01634 iks_delete(query); 01635 ASTOBJ_UNREF(client, aji_client_destroy); 01636 return IKS_FILTER_EAT; 01637 }
| static int aji_reload | ( | int | reload | ) | [static] |
Definition at line 3460 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().
03461 { 03462 int res; 03463 03464 ASTOBJ_CONTAINER_MARKALL(&clients); 03465 if (!(res = aji_load_config(reload))) { 03466 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 03467 return 0; 03468 } else if (res == -1) 03469 return 1; 03470 03471 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); 03472 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03473 ASTOBJ_RDLOCK(iterator); 03474 if (iterator->state == AJI_DISCONNECTED) { 03475 if (!iterator->thread) 03476 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 03477 } else if (iterator->state == AJI_CONNECTING) 03478 aji_get_roster(iterator); 03479 ASTOBJ_UNLOCK(iterator); 03480 }); 03481 03482 return 1; 03483 }
| static int aji_send_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 919 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_WARNING, and s.
Referenced by load_module().
00920 { 00921 struct aji_client *client = NULL; 00922 char *s; 00923 AST_DECLARE_APP_ARGS(args, 00924 AST_APP_ARG(sender); 00925 AST_APP_ARG(recipient); 00926 AST_APP_ARG(message); 00927 ); 00928 00929 if (!data) { 00930 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 00931 return -1; 00932 } 00933 s = ast_strdupa(data); 00934 00935 AST_STANDARD_APP_ARGS(args, s); 00936 if (args.argc < 3) { 00937 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 00938 return -1; 00939 } 00940 00941 if (!(client = ast_aji_get_client(args.sender))) { 00942 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00943 return -1; 00944 } 00945 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) { 00946 ast_aji_send_chat(client, args.recipient, args.message); 00947 } 00948 return 0; 00949 }
| static int aji_send_header | ( | struct aji_client * | client, | |
| const char * | to | |||
| ) | [static] |
Definition at line 1173 of file res_jabber.c.
References aji_send_raw(), len(), msg, and aji_client::name_space.
Referenced by aji_act_hook().
01174 { 01175 char *msg; 01176 int len, err; 01177 01178 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 01179 msg = iks_malloc(len); 01180 if (!msg) 01181 return IKS_NOMEM; 01182 sprintf(msg, "<?xml version='1.0'?>" 01183 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 01184 "%s' to='%s' version='1.0'>", client->name_space, to); 01185 err = aji_send_raw(client, msg); 01186 iks_free(msg); 01187 if (err != IKS_OK) 01188 return err; 01189 01190 return IKS_OK; 01191 }
| static int aji_send_raw | ( | struct aji_client * | client, | |
| const char * | xmlstr | |||
| ) | [static] |
Definition at line 1213 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().
01214 { 01215 int ret; 01216 #ifdef HAVE_OPENSSL 01217 int len = strlen(xmlstr); 01218 01219 if (aji_is_secure(client)) { 01220 ret = SSL_write(client->ssl_session, xmlstr, len); 01221 if (ret) { 01222 /* Log the message here, because iksemel's logHook is 01223 unaccessible */ 01224 aji_log_hook(client, xmlstr, len, 0); 01225 return IKS_OK; 01226 } 01227 } 01228 #endif 01229 /* If needed, data will be sent unencrypted, and logHook will 01230 be called inside iks_send_raw */ 01231 ret = iks_send_raw(client->p, xmlstr); 01232 if (ret != IKS_OK) 01233 return ret; 01234 01235 return IKS_OK; 01236 }
| static void aji_set_presence | ( | struct aji_client * | client, | |
| char * | to, | |||
| char * | from, | |||
| int | level, | |||
| char * | desc | |||
| ) | [static] |
Definition at line 2829 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().
02830 { 02831 int res = 0; 02832 iks *presence = iks_make_pres(level, desc); 02833 iks *cnode = iks_new("c"); 02834 iks *priority = iks_new("priority"); 02835 char priorityS[10]; 02836 02837 if (presence && cnode && client && priority) { 02838 if (to) 02839 iks_insert_attrib(presence, "to", to); 02840 if (from) 02841 iks_insert_attrib(presence, "from", from); 02842 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 02843 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 02844 iks_insert_node(presence, priority); 02845 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 02846 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 02847 iks_insert_attrib(cnode, "ext", "voice-v1"); 02848 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 02849 iks_insert_node(presence, cnode); 02850 res = ast_aji_send(client, presence); 02851 } else 02852 ast_log(LOG_ERROR, "Out of memory.\n"); 02853 02854 iks_delete(cnode); 02855 iks_delete(presence); 02856 iks_delete(priority); 02857 }
| static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2974 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.
02975 { 02976 struct aji_resource *resource; 02977 struct aji_client *client; 02978 02979 switch (cmd) { 02980 case CLI_INIT: 02981 e->command = "jabber show buddies"; 02982 e->usage = 02983 "Usage: jabber show buddies\n" 02984 " Shows buddy lists of our clients\n"; 02985 return NULL; 02986 case CLI_GENERATE: 02987 return NULL; 02988 } 02989 02990 ast_cli(a->fd, "Jabber buddy lists\n"); 02991 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02992 ast_cli(a->fd,"Client: %s\n", iterator->user); 02993 client = iterator; 02994 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02995 ASTOBJ_RDLOCK(iterator); 02996 ast_cli(a->fd,"\tBuddy:\t%s\n", iterator->name); 02997 if (!iterator->resources) 02998 ast_cli(a->fd,"\t\tResource: None\n"); 02999 for (resource = iterator->resources; resource; resource = resource->next) { 03000 ast_cli(a->fd,"\t\tResource: %s\n", resource->resource); 03001 if (resource->cap) { 03002 ast_cli(a->fd,"\t\t\tnode: %s\n", resource->cap->parent->node); 03003 ast_cli(a->fd,"\t\t\tversion: %s\n", resource->cap->version); 03004 ast_cli(a->fd,"\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 03005 } 03006 ast_cli(a->fd,"\t\tStatus: %d\n", resource->status); 03007 ast_cli(a->fd,"\t\tPriority: %d\n", resource->priority); 03008 } 03009 ASTOBJ_UNLOCK(iterator); 03010 }); 03011 iterator = client; 03012 }); 03013 return CLI_SUCCESS; 03014 }
| static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2928 of file res_jabber.c.
References AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.
02929 { 02930 char *status; 02931 int count = 0; 02932 02933 switch (cmd) { 02934 case CLI_INIT: 02935 e->command = "jabber show connected"; 02936 e->usage = 02937 "Usage: jabber show connected\n" 02938 " Shows state of clients and components\n"; 02939 return NULL; 02940 case CLI_GENERATE: 02941 return NULL; 02942 } 02943 02944 ast_cli(a->fd, "Jabber Users and their status:\n"); 02945 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 02946 ASTOBJ_RDLOCK(iterator); 02947 count++; 02948 switch (iterator->state) { 02949 case AJI_DISCONNECTED: 02950 status = "Disconnected"; 02951 break; 02952 case AJI_CONNECTING: 02953 status = "Connecting"; 02954 break; 02955 case AJI_CONNECTED: 02956 status = "Connected"; 02957 break; 02958 default: 02959 status = "Unknown"; 02960 } 02961 ast_cli(a->fd, " User: %s - %s\n", iterator->user, status); 02962 ASTOBJ_UNLOCK(iterator); 02963 }); 02964 ast_cli(a->fd, "----\n"); 02965 ast_cli(a->fd, " Number of users: %d\n", count); 02966 return CLI_SUCCESS; 02967 }
| static int aji_start_sasl | ( | struct aji_client * | client, | |
| enum ikssasltype | type, | |||
| char * | username, | |||
| char * | pass | |||
| ) | [static] |
Definition at line 1279 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().
01280 { 01281 iks *x = NULL; 01282 int len; 01283 char *s; 01284 char *base64; 01285 01286 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 01287 iks_start_sasl is an iksemel API function and relies on GnuTLS, 01288 whereas we use OpenSSL */ 01289 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 01290 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 01291 if (!(type & IKS_STREAM_SASL_PLAIN)) { 01292 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 01293 return IKS_NET_NOTSUPP; 01294 } 01295 01296 x = iks_new("auth"); 01297 if (!x) { 01298 ast_log(LOG_ERROR, "Out of memory.\n"); 01299 return IKS_NET_NOTSUPP; 01300 } 01301 01302 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 01303 len = strlen(username) + strlen(pass) + 3; 01304 s = alloca(len); 01305 base64 = alloca((len + 2) * 4 / 3); 01306 iks_insert_attrib(x, "mechanism", "PLAIN"); 01307 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 01308 01309 /* exclude the NULL training byte from the base64 encoding operation 01310 as some XMPP servers will refuse it. 01311 The format for authentication is [authzid]\0authcid\0password 01312 not [authzid]\0authcid\0password\0 */ 01313 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 01314 iks_insert_cdata(x, base64, 0); 01315 ast_aji_send(client, x); 01316 iks_delete(x); 01317 01318 return IKS_OK; 01319 }
| static int aji_status_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 559 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, 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().
00560 { 00561 struct aji_client *client = NULL; 00562 struct aji_buddy *buddy = NULL; 00563 struct aji_resource *r = NULL; 00564 char *s = NULL; 00565 int stat = 7; 00566 char status[2]; 00567 static int deprecation_warning = 0; 00568 AST_DECLARE_APP_ARGS(args, 00569 AST_APP_ARG(sender); 00570 AST_APP_ARG(jid); 00571 AST_APP_ARG(variable); 00572 ); 00573 AST_DECLARE_APP_ARGS(jid, 00574 AST_APP_ARG(screenname); 00575 AST_APP_ARG(resource); 00576 ); 00577 00578 if (deprecation_warning++ % 10 == 0) 00579 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00580 00581 if (!data) { 00582 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00583 return 0; 00584 } 00585 s = ast_strdupa(data); 00586 AST_STANDARD_APP_ARGS(args, s); 00587 00588 if (args.argc != 3) { 00589 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00590 return -1; 00591 } 00592 00593 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00594 if (jid.argc < 1 || jid.argc > 2) { 00595 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00596 return -1; 00597 } 00598 00599 if (!(client = ast_aji_get_client(args.sender))) { 00600 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00601 return -1; 00602 } 00603 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00604 if (!buddy) { 00605 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00606 return -1; 00607 } 00608 r = aji_find_resource(buddy, jid.resource); 00609 if (!r && buddy->resources) 00610 r = buddy->resources; 00611 if (!r) 00612 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00613 else 00614 stat = r->status; 00615 snprintf(status, sizeof(status), "%d", stat); 00616 pbx_builtin_setvar_helper(chan, args.variable, status); 00617 return 0; 00618 }
| static char * aji_test | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3021 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.
03022 { 03023 struct aji_client *client; 03024 struct aji_resource *resource; 03025 const char *name = "asterisk"; 03026 struct aji_message *tmp; 03027 03028 switch (cmd) { 03029 case CLI_INIT: 03030 e->command = "jabber test"; 03031 e->usage = 03032 "Usage: jabber test [client]\n" 03033 " Sends test message for debugging purposes. A specific client\n" 03034 " as configured in jabber.conf can be optionally specified.\n"; 03035 return NULL; 03036 case CLI_GENERATE: 03037 return NULL; 03038 } 03039 03040 if (a->argc > 3) 03041 return CLI_SHOWUSAGE; 03042 else if (a->argc == 3) 03043 name = a->argv[2]; 03044 03045 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03046 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03047 return CLI_FAILURE; 03048 } 03049 03050 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 03051 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 03052 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03053 ASTOBJ_RDLOCK(iterator); 03054 ast_verbose("User: %s\n", iterator->name); 03055 for (resource = iterator->resources; resource; resource = resource->next) { 03056 ast_verbose("Resource: %s\n", resource->resource); 03057 if (resource->cap) { 03058 ast_verbose(" client: %s\n", resource->cap->parent->node); 03059 ast_verbose(" version: %s\n", resource->cap->version); 03060 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 03061 } 03062 ast_verbose(" Priority: %d\n", resource->priority); 03063 ast_verbose(" Status: %d\n", resource->status); 03064 ast_verbose(" Message: %s\n", S_OR(resource->description,"")); 03065 } 03066 ASTOBJ_UNLOCK(iterator); 03067 }); 03068 ast_verbose("\nOooh a working message stack!\n"); 03069 AST_LIST_LOCK(&client->messages); 03070 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 03071 //ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 03072 } 03073 AST_LIST_UNLOCK(&client->messages); 03074 ASTOBJ_UNREF(client, aji_client_destroy); 03075 03076 return CLI_SUCCESS; 03077 }
| 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 2304 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02305 { 02306 int res = 0; 02307 iks *iq = NULL; 02308 iq = iks_new("iq"); 02309 02310 if (iq && client) { 02311 iks_insert_attrib(iq, "type", "get"); 02312 iks_insert_attrib(iq, "to", server); 02313 iks_insert_attrib(iq, "id", client->mid); 02314 ast_aji_increment_mid(client->mid); 02315 ast_aji_send(client, iq); 02316 } else 02317 ast_log(LOG_ERROR, "Out of memory.\n"); 02318 02319 iks_delete(iq); 02320 02321 return res; 02322 }
| 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 2800 of file res_jabber.c.
References aji_client_destroy(), ast_verb, ASTOBJ_UNREF, and aji_client::p.
Referenced by unload_module().
02801 { 02802 if (client) { 02803 ast_verb(4, "JABBER: Disconnecting\n"); 02804 #ifdef HAVE_OPENSSL 02805 if (client->stream_flags & SECURE) { 02806 SSL_shutdown(client->ssl_session); 02807 SSL_CTX_free(client->ssl_context); 02808 SSL_free(client->ssl_session); 02809 } 02810 #endif 02811 iks_disconnect(client->p); 02812 iks_parser_delete(client->p); 02813 ASTOBJ_UNREF(client, aji_client_destroy); 02814 } 02815 02816 return 1; 02817 }
| struct aji_client* ast_aji_get_client | ( | const char * | name | ) | [read] |
grab a aji_client structure by label name or JID (without the resource string)
| name | label or JID |
Definition at line 3382 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, clients, and strsep().
Referenced by acf_jabberreceive_read(), 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().
03383 { 03384 struct aji_client *client = NULL; 03385 char *aux = NULL; 03386 03387 client = ASTOBJ_CONTAINER_FIND(&clients, name); 03388 if (!client && strchr(name, '@')) { 03389 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03390 aux = ast_strdupa(iterator->user); 03391 if (strchr(aux, '/')) { 03392 /* strip resource for comparison */ 03393 aux = strsep(&aux, "/"); 03394 } 03395 if (!strncasecmp(aux, name, strlen(aux))) { 03396 client = iterator; 03397 } 03398 }); 03399 } 03400 03401 return client; 03402 }
| struct aji_client_container* ast_aji_get_clients | ( | void | ) | [read] |
Definition at line 3404 of file res_jabber.c.
References clients.
Referenced by gtalk_load_config(), and jingle_load_config().
03405 { 03406 return &clients; 03407 }
| void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
| mid | char. |
Definition at line 2452 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().
02453 { 02454 int i = 0; 02455 02456 for (i = strlen(mid) - 1; i >= 0; i--) { 02457 if (mid[i] != 'z') { 02458 mid[i] = mid[i] + 1; 02459 i = 0; 02460 } else 02461 mid[i] = 'a'; 02462 } 02463 }
| int ast_aji_invite_chat | ( | struct aji_client * | client, | |
| char * | user, | |||
| char * | room, | |||
| char * | message | |||
| ) |
invite to a chatroom.
Definition at line 2361 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02362 { 02363 int res = 0; 02364 iks *invite, *body, *namespace; 02365 02366 invite = iks_new("message"); 02367 body = iks_new("body"); 02368 namespace = iks_new("x"); 02369 if (client && invite && body && namespace) { 02370 iks_insert_attrib(invite, "to", user); 02371 iks_insert_attrib(invite, "id", client->mid); 02372 ast_aji_increment_mid(client->mid); 02373 iks_insert_cdata(body, message, 0); 02374 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02375 iks_insert_attrib(namespace, "jid", room); 02376 iks_insert_node(invite, body); 02377 iks_insert_node(invite, namespace); 02378 res = ast_aji_send(client, invite); 02379 } else 02380 ast_log(LOG_ERROR, "Out of memory.\n"); 02381 02382 iks_delete(body); 02383 iks_delete(namespace); 02384 iks_delete(invite); 02385 02386 return res; 02387 }
| 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 2330 of file res_jabber.c.
References ast_aji_send(), ast_log(), and LOG_ERROR.
02331 { 02332 int res = 0; 02333 iks *presence = NULL, *priority = NULL; 02334 presence = iks_new("presence"); 02335 priority = iks_new("priority"); 02336 if (presence && priority && client) { 02337 iks_insert_cdata(priority, "0", 1); 02338 iks_insert_attrib(presence, "to", room); 02339 iks_insert_node(presence, priority); 02340 res = ast_aji_send(client, presence); 02341 iks_insert_cdata(priority, "5", 1); 02342 iks_insert_attrib(presence, "to", room); 02343 res = ast_aji_send(client, presence); 02344 } else 02345 ast_log(LOG_ERROR, "Out of memory.\n"); 02346 02347 iks_delete(presence); 02348 iks_delete(priority); 02349 02350 return res; 02351 }
| 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 1199 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().
01200 { 01201 return aji_send_raw(client, iks_string(iks_stack(x), x)); 01202 }
| 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 |
| IKS_OK | success | |
| -1 | failure |
Definition at line 2273 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(), gtalk_sendtext(), jingle_sendtext(), and manager_jabber_send().
02274 { 02275 int res = 0; 02276 iks *message_packet = NULL; 02277 02278 if (client->state != AJI_CONNECTED) { 02279 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02280 return -1; 02281 } 02282 02283 message_packet = iks_make_msg(IKS_TYPE_CHAT, address, message); 02284 if (!message_packet) { 02285 ast_log(LOG_ERROR, "Out of memory.\n"); 02286 return -1; 02287 } 02288 02289 iks_insert_attrib(message_packet, "from", client->jid->full); 02290 res = ast_aji_send(client, message_packet); 02291 iks_delete(message_packet); 02292 02293 return res; 02294 }
| static int delete_old_messages | ( | struct aji_client * | client, | |
| char * | from | |||
| ) | [static] |
Definition at line 859 of file res_jabber.c.
References aji_message_destroy(), aji_message::arrived, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_tvdiff_sec(), ast_tvnow(), aji_message::from, aji_message::list, LOG_ERROR, aji_client::message_timeout, and aji_client::messages.
Referenced by aji_handle_message(), and delete_old_messages_all().
00860 { 00861 int deleted = 0; 00862 int isold = 0; 00863 struct aji_message *tmp = NULL; 00864 if (!client) { 00865 ast_log(LOG_ERROR, "Cannot find our XMPP client\n"); 00866 return -1; 00867 } 00868 00869 /* remove old messages */ 00870 AST_LIST_LOCK(&client->messages); 00871 if (AST_LIST_EMPTY(&client->messages)) { 00872 AST_LIST_UNLOCK(&client->messages); 00873 return 0; 00874 } 00875 00876 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00877 if (isold) { 00878 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00879 AST_LIST_REMOVE_CURRENT(list); 00880 aji_message_destroy(tmp); 00881 deleted ++; 00882 } 00883 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00884 isold = 1; 00885 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00886 AST_LIST_REMOVE_CURRENT(list); 00887 aji_message_destroy(tmp); 00888 deleted ++; 00889 } 00890 } 00891 } 00892 AST_LIST_TRAVERSE_SAFE_END; 00893 AST_LIST_UNLOCK(&client->messages); 00894 00895 return deleted; 00896 }
| static int delete_old_messages_all | ( | struct aji_client * | client | ) | [static] |
Definition at line 906 of file res_jabber.c.
References delete_old_messages().
Referenced by aji_recv_loop().
00907 { 00908 return delete_old_messages(client, NULL); 00909 }
| static int gtalk_yuck | ( | iks * | node | ) | [static] |
Definition at line 514 of file res_jabber.c.
Referenced by aji_handle_presence().
00515 { 00516 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) 00517 return 1; 00518 return 0; 00519 }
| static iks * jabber_make_auth | ( | iksid * | id, | |
| const char * | pass, | |||
| const char * | sid | |||
| ) | [static] |
Definition at line 529 of file res_jabber.c.
References ast_sha1_hash(), and buf.
Referenced by aji_act_hook().
00530 { 00531 iks *x, *y; 00532 x = iks_new("iq"); 00533 iks_insert_attrib(x, "type", "set"); 00534 y = iks_insert(x, "query"); 00535 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00536 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00537 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00538 if (sid) { 00539 char buf[41]; 00540 char sidpass[100]; 00541 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00542 ast_sha1_hash(buf, sidpass); 00543 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00544 } else { 00545 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00546 } 00547 return x; 00548 }
| static int load_module | ( | void | ) | [static] |
Definition at line 3521 of file res_jabber.c.
References aji_reload(), aji_send_exec(), aji_status_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_cond_init(), ast_custom_function_register, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_mutex_init(), ast_register_application_xml, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, and manager_jabber_send().
03522 { 03523 ASTOBJ_CONTAINER_INIT(&clients); 03524 if (!aji_reload(0)) 03525 return AST_MODULE_LOAD_DECLINE; 03526 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 03527 ast_register_application_xml(app_ajisend, aji_send_exec); 03528 ast_register_application_xml(app_ajistatus, aji_status_exec); 03529 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 03530 ast_custom_function_register(&jabberstatus_function); 03531 ast_custom_function_register(&jabberreceive_function); 03532 03533 ast_mutex_init(&messagelock); 03534 ast_cond_init(&message_received_condition, NULL); 03535 return 0; 03536 }
| static int manager_jabber_send | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3416 of file res_jabber.c.
References ast_aji_get_client(), ast_aji_send_chat(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by load_module().
03417 { 03418 struct aji_client *client = NULL; 03419 const char *id = astman_get_header(m,"ActionID"); 03420 const char *jabber = astman_get_header(m,"Jabber"); 03421 const char *screenname = astman_get_header(m,"ScreenName"); 03422 const char *message = astman_get_header(m,"Message"); 03423 03424 if (ast_strlen_zero(jabber)) { 03425 astman_send_error(s, m, "No transport specified"); 03426 return 0; 03427 } 03428 if (ast_strlen_zero(screenname)) { 03429 astman_send_error(s, m, "No ScreenName specified"); 03430 return 0; 03431 } 03432 if (ast_strlen_zero(message)) { 03433 astman_send_error(s, m, "No Message specified"); 03434 return 0; 03435 } 03436 03437 astman_send_ack(s, m, "Attempting to send Jabber Message"); 03438 client = ast_aji_get_client(jabber); 03439 if (!client) { 03440 astman_send_error(s, m, "Could not find Sender"); 03441 return 0; 03442 } 03443 if (strchr(screenname, '@') && message) { 03444 ast_aji_send_chat(client, screenname, message); 03445 astman_append(s, "Response: Success\r\n"); 03446 } else { 03447 astman_append(s, "Response: Error\r\n"); 03448 } 03449 if (!ast_strlen_zero(id)) { 03450 astman_append(s, "ActionID: %s\r\n",id); 03451 } 03452 astman_append(s, "\r\n"); 03453 return 0; 03454 }
| static int reload | ( | void | ) | [static] |
Definition at line 3542 of file res_jabber.c.
References aji_reload().
03543 { 03544 aji_reload(1); 03545 return 0; 03546 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3489 of file res_jabber.c.
References aji_client_destroy(), AJI_DISCONNECTING, ARRAY_LEN, ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_custom_function_unregister(), ast_debug, ast_manager_unregister(), ast_mutex_destroy(), ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and clients.
03490 { 03491 03492 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 03493 ast_unregister_application(app_ajisend); 03494 ast_unregister_application(app_ajistatus); 03495 ast_manager_unregister("JabberSend"); 03496 ast_custom_function_unregister(&jabberstatus_function); 03497 ast_custom_function_unregister(&jabberreceive_function); 03498 03499 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 03500 ASTOBJ_RDLOCK(iterator); 03501 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 03502 iterator->state = AJI_DISCONNECTING; 03503 ast_aji_disconnect(iterator); 03504 pthread_join(iterator->thread, NULL); 03505 ASTOBJ_UNLOCK(iterator); 03506 }); 03507 03508 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); 03509 ASTOBJ_CONTAINER_DESTROY(&clients); 03510 03511 ast_cond_destroy(&message_received_condition); 03512 ast_mutex_destroy(&messagelock); 03513 03514 return 0; 03515 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3552 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
Definition at line 336 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 344 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 346 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3552 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL [static] |
struct aji_client_container clients [static] |
Definition at line 348 of file res_jabber.c.
Referenced by aji_create_client(), aji_do_set_debug(), aji_reload(), aji_show_buddies(), aji_show_clients(), aji_test(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), jingle_load_config(), load_module(), and unload_module().
struct ast_flags globalflags = { AJI_AUTOREGISTER } [static] |
struct ast_custom_function jabberreceive_function [static] |
Initial value:
{
.name = "JABBER_RECEIVE",
.read = acf_jabberreceive_read,
}
Definition at line 845 of file res_jabber.c.
struct ast_custom_function jabberstatus_function [static] |
Initial value:
{
.name = "JABBER_STATUS",
.read = acf_jabberstatus_read,
}
Definition at line 681 of file res_jabber.c.
ast_cond_t message_received_condition [static] |
Definition at line 350 of file res_jabber.c.
ast_mutex_t messagelock [static] |
Definition at line 351 of file res_jabber.c.
1.5.6