#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"
#include "asterisk/event.h"
#include "asterisk/devicestate.h"
#include "asterisk/message.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 iks * | aji_build_node_config (iks *pubsub, const char *node_type, const char *collection_name) |
| static iks * | aji_build_node_request (struct aji_client *client, const char *collection) |
| Build the a node request. | |
| static iks * | aji_build_publish_skeleton (struct aji_client *client, const char *node, const char *event_type) |
| Build the skeleton of a publish. | |
| static char * | aji_cli_create_collection (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Method to expose PubSub collection node creation via CLI. | |
| static char * | aji_cli_create_leafnode (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Method to expose PubSub leaf node creation via CLI. | |
| static char * | aji_cli_delete_pubsub_node (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Method to expose PubSub node deletion via CLI. | |
| static char * | aji_cli_list_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Method to expose PubSub node list via CLI. | |
| static char * | aji_cli_purge_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Method to purge PubSub nodes via CLI. | |
| static int | aji_client_connect (void *data, ikspak *pak) |
| static int | aji_client_info_handler (void *data, ikspak *pak) |
| static void | aji_create_affiliations (struct aji_client *client, const char *node) |
| Add Owner affiliations for pubsub node. | |
| 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 void | aji_create_pubsub_collection (struct aji_client *client, const char *collection_name) |
| Create a PubSub collection node. | |
| static void | aji_create_pubsub_leaf (struct aji_client *client, const char *collection_name, const char *leaf_name) |
| Create a PubSub leaf node. | |
| static iks * | aji_create_pubsub_node (struct aji_client *client, const char *node_type, const char *name, const char *collection_name) |
| Create a pubsub node. | |
| static int | aji_delete_node_list (void *data, ikspak *pak) |
| Delete pubsub item lists. | |
| static void | aji_delete_pubsub_node (struct aji_client *client, const char *node_name) |
| Delete a PubSub node. | |
| static void | aji_devstate_cb (const struct ast_event *ast_event, void *data) |
| Callback function for device state events. | |
| 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 int | aji_handle_pubsub_error (void *data, ikspak *pak) |
| static int | aji_handle_pubsub_event (void *data, ikspak *pak) |
| Callback for handling PubSub events. | |
| static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
| static void | aji_init_event_distribution (struct aji_client *client) |
| Initialize collections for event distribution. | |
| 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_join_exec (struct ast_channel *chan, const char *data) |
| Application to join a chat room. | |
| static int | aji_leave_exec (struct ast_channel *chan, const char *data) |
| Application to leave a chat room. | |
| 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_mwi_cb (const struct ast_event *ast_event, void *data) |
| Callback function for MWI events. | |
| static void | aji_pruneregister (struct aji_client *client) |
| static void | aji_publish_device_state (struct aji_client *client, const char *device, const char *device_state) |
| Publish device state to a PubSub node. | |
| static void | aji_publish_mwi (struct aji_client *client, const char *mailbox, const char *context, const char *oldmsgs, const char *newmsgs) |
| Publish MWI to a PubSub node. | |
| static iks * | aji_pubsub_iq_create (struct aji_client *client, const char *type) |
| Create an IQ packet. | |
| static void | aji_pubsub_purge_nodes (struct aji_client *client, const char *collection_name) |
| static void | aji_pubsub_subscribe (struct aji_client *client, const char *node) |
| Subscribe to a PubSub node. | |
| static int | aji_receive_node_list (void *data, ikspak *pak) |
| Receive pubsub item lists. | |
| 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 void | aji_request_pubsub_nodes (struct aji_client *client, const char *collection) |
| Request item list from pubsub. | |
| 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 int | aji_send_raw_chat (struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message) |
| sends messages. | |
| static int | aji_sendgroup_exec (struct ast_channel *chan, const char *data) |
| Application to send a message to a groupchat. | |
| static int | aji_set_group_presence (struct aji_client *client, char *room, int level, char *nick, char *desc) |
| 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) |
| void | ast_aji_buddy_destroy (struct aji_buddy *obj) |
| void | ast_aji_client_destroy (struct aji_client *obj) |
| 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. Bumps the refcount. (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, char *nick) |
| join a chatroom. | |
| int | ast_aji_leave_chat (struct aji_client *client, char *room, char *nick) |
| leave 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. | |
| int | ast_aji_send_groupchat (struct aji_client *client, const char *nick, const char *address, const char *message) |
| sends message to a groupchat Prior to sending messages to a groupchat, one must be connected to it. | |
| 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 | msg_send_cb (const struct ast_msg *msg, const char *to, const char *from) |
| 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 | AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
| static struct ast_cli_entry | aji_cli [] |
| static char * | app_ajijoin = "JabberJoin" |
| static char * | app_ajileave = "JabberLeave" |
| static char * | app_ajisend = "JabberSend" |
| static char * | app_ajisendgroup = "JabberSendGroup" |
| 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_event_sub * | device_state_sub = NULL |
| static struct ast_flags | globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } |
| 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 |
| static struct ast_msg_tech | msg_tech |
| static struct ast_event_sub * | mwi_sub = NULL |
| static struct ast_flags | pubsubflags = { 0 } |
| PubSub flags, initialized to default values. | |
References:
Definition in file res_jabber.c.
| #define JABBER_CONFIG "jabber.conf" |
Definition at line 286 of file res_jabber.c.
Referenced by aji_load_config().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 4850 of file res_jabber.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4850 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 777 of file res_jabber.c.
References AJI_MAX_JIDLEN, aji_message_destroy(), args, aji_message::arrived, ast_aji_client_destroy(), ast_aji_get_client(), AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_name(), 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, and parse().
00778 { 00779 char *aux = NULL, *parse = NULL; 00780 int timeout; 00781 int jidlen, resourcelen; 00782 struct timeval start; 00783 long diff = 0; 00784 struct aji_client *client = NULL; 00785 int found = 0; 00786 struct aji_message *tmp = NULL; 00787 AST_DECLARE_APP_ARGS(args, 00788 AST_APP_ARG(account); 00789 AST_APP_ARG(jid); 00790 AST_APP_ARG(timeout); 00791 ); 00792 AST_DECLARE_APP_ARGS(jid, 00793 AST_APP_ARG(screenname); 00794 AST_APP_ARG(resource); 00795 ); 00796 00797 if (ast_strlen_zero(data)) { 00798 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00799 return -1; 00800 } 00801 00802 parse = ast_strdupa(data); 00803 AST_STANDARD_APP_ARGS(args, parse); 00804 00805 if (args.argc < 2 || args.argc > 3) { 00806 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00807 return -1; 00808 } 00809 00810 parse = ast_strdupa(args.jid); 00811 AST_NONSTANDARD_APP_ARGS(jid, parse, '/'); 00812 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) { 00813 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse); 00814 return -1; 00815 } 00816 00817 if (ast_strlen_zero(args.timeout)) { 00818 timeout = 20; 00819 } else { 00820 sscanf(args.timeout, "%d", &timeout); 00821 if (timeout <= 0) { 00822 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 00823 return -1; 00824 } 00825 } 00826 00827 jidlen = strlen(jid.screenname); 00828 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource); 00829 00830 client = ast_aji_get_client(args.account); 00831 if (!client) { 00832 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account); 00833 return -1; 00834 } 00835 00836 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid); 00837 00838 start = ast_tvnow(); 00839 00840 if (ast_autoservice_start(chan) < 0) { 00841 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", ast_channel_name(chan)); 00842 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00843 return -1; 00844 } 00845 00846 /* search the messages list, grab the first message that matches with 00847 * the from JID we're expecting, and remove it from the messages list */ 00848 while (diff < timeout) { 00849 struct timespec ts = { 0, }; 00850 struct timeval wait; 00851 int res; 00852 00853 wait = ast_tvadd(start, ast_tv(timeout, 0)); 00854 ts.tv_sec = wait.tv_sec; 00855 ts.tv_nsec = wait.tv_usec * 1000; 00856 00857 /* wait up to timeout seconds for an incoming message */ 00858 ast_mutex_lock(&messagelock); 00859 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts); 00860 ast_mutex_unlock(&messagelock); 00861 if (res == ETIMEDOUT) { 00862 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout); 00863 break; 00864 } 00865 00866 AST_LIST_LOCK(&client->messages); 00867 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00868 if (jid.argc == 1) { 00869 /* no resource provided, compare bare JIDs */ 00870 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00871 continue; 00872 } 00873 } else { 00874 /* resource appended, compare bare JIDs and resources */ 00875 char *resource = strchr(tmp->from, '/'); 00876 if (!resource || strlen(resource) == 0) { 00877 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from); 00878 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00879 continue; 00880 } 00881 } else { 00882 resource ++; 00883 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) { 00884 continue; 00885 } 00886 } 00887 } 00888 /* check if the message is not too old */ 00889 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00890 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from); 00891 AST_LIST_REMOVE_CURRENT(list); 00892 aji_message_destroy(tmp); 00893 continue; 00894 } 00895 found = 1; 00896 aux = ast_strdupa(tmp->message); 00897 AST_LIST_REMOVE_CURRENT(list); 00898 aji_message_destroy(tmp); 00899 break; 00900 } 00901 AST_LIST_TRAVERSE_SAFE_END; 00902 AST_LIST_UNLOCK(&client->messages); 00903 if (found) { 00904 break; 00905 } 00906 00907 /* check timeout */ 00908 diff = ast_tvdiff_ms(ast_tvnow(), start); 00909 } 00910 00911 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00912 if (ast_autoservice_stop(chan) < 0) { 00913 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", ast_channel_name(chan)); 00914 } 00915 00916 /* return if we timed out */ 00917 if (!found) { 00918 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); 00919 return -1; 00920 } 00921 ast_copy_string(buf, aux, buflen); 00922 00923 return 0; 00924 }
| static int acf_jabberstatus_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 706 of file res_jabber.c.
References aji_find_resource(), args, ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_aji_get_client(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_resource::resource, aji_buddy::resources, and aji_resource::status.
00707 { 00708 struct aji_client *client = NULL; 00709 struct aji_buddy *buddy = NULL; 00710 struct aji_resource *r = NULL; 00711 int stat = 7; 00712 AST_DECLARE_APP_ARGS(args, 00713 AST_APP_ARG(sender); 00714 AST_APP_ARG(jid); 00715 ); 00716 AST_DECLARE_APP_ARGS(jid, 00717 AST_APP_ARG(screenname); 00718 AST_APP_ARG(resource); 00719 ); 00720 00721 if (!data) { 00722 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00723 return 0; 00724 } 00725 AST_STANDARD_APP_ARGS(args, data); 00726 00727 if (args.argc != 2) { 00728 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00729 return -1; 00730 } 00731 00732 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00733 if (jid.argc < 1 || jid.argc > 2) { 00734 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00735 return -1; 00736 } 00737 00738 if (!(client = ast_aji_get_client(args.sender))) { 00739 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00740 return -1; 00741 } 00742 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00743 if (!buddy) { 00744 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00745 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00746 return -1; 00747 } 00748 r = aji_find_resource(buddy, jid.resource); 00749 if (!r && buddy->resources) { 00750 r = buddy->resources; 00751 } 00752 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00753 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00754 if (!r) { 00755 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00756 } else { 00757 stat = r->status; 00758 } 00759 snprintf(buf, buflen, "%d", stat); 00760 return 0; 00761 }
| static int aji_act_hook | ( | void * | data, | |
| int | type, | |||
| iks * | node | |||
| ) | [static] |
Definition at line 1613 of file res_jabber.c.
References aji_client_connect(), AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, AJI_DISCONNECTING, aji_handle_iq(), aji_handle_message(), aji_handle_presence(), aji_handle_subscribe(), aji_is_secure(), AJI_MAX_ATTRLEN, aji_recv(), aji_send_header(), aji_send_raw(), aji_start_sasl(), asprintf, ast_aji_client_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_debug, ast_free, ast_log(), ast_sha1_hash(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::authorized, aji_client::component, aji_client::f, jabber_make_auth(), aji_client::jid, LOG_ERROR, LOG_WARNING, aji_client::mid, aji_client::password, secret, aji_client::state, aji_client::usesasl, and aji_client::usetls.
Referenced by aji_create_client().
01614 { 01615 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01616 ikspak *pak = NULL; 01617 iks *auth = NULL; 01618 int features = 0; 01619 01620 if (!node) { 01621 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 01622 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01623 return IKS_HOOK; 01624 } 01625 01626 if (client->state == AJI_DISCONNECTING) { 01627 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01628 return IKS_HOOK; 01629 } 01630 01631 pak = iks_packet(node); 01632 01633 /* work around iksemel's impossibility to recognize node names 01634 * containing a semicolon. Set the namespace of the corresponding 01635 * node accordingly. */ 01636 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) { 01637 char *node_ns = NULL; 01638 char attr[AJI_MAX_ATTRLEN]; 01639 char *node_name = iks_name(iks_child(node)); 01640 char *aux = strchr(node_name, ':') + 1; 01641 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name); 01642 node_ns = iks_find_attrib(iks_child(node), attr); 01643 if (node_ns) { 01644 pak->ns = node_ns; 01645 pak->query = iks_child(node); 01646 } 01647 } 01648 01649 01650 if (!client->component) { /*client */ 01651 switch (type) { 01652 case IKS_NODE_START: 01653 if (client->usetls && !aji_is_secure(client)) { 01654 #ifndef HAVE_OPENSSL 01655 ast_log(LOG_ERROR, "TLS connection cannot be established. Please install OpenSSL and its development libraries on this system, or disable the TLS option in your configuration file\n"); 01656 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01657 return IKS_HOOK; 01658 #else 01659 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 01660 ast_log(LOG_ERROR, "Could not start TLS\n"); 01661 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01662 return IKS_HOOK; 01663 } 01664 #endif 01665 break; 01666 } 01667 if (!client->usesasl) { 01668 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); 01669 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 01670 if (auth) { 01671 iks_insert_attrib(auth, "id", client->mid); 01672 iks_insert_attrib(auth, "to", client->jid->server); 01673 ast_aji_increment_mid(client->mid); 01674 ast_aji_send(client, auth); 01675 iks_delete(auth); 01676 } else { 01677 ast_log(LOG_ERROR, "Out of memory.\n"); 01678 } 01679 } 01680 break; 01681 01682 case IKS_NODE_NORMAL: 01683 #ifdef HAVE_OPENSSL 01684 if (client->stream_flags & TRY_SECURE) { 01685 if (!strcmp("proceed", iks_name(node))) { 01686 return aji_tls_handshake(client); 01687 } 01688 } 01689 #endif 01690 if (!strcmp("stream:features", iks_name(node))) { 01691 features = iks_stream_features(node); 01692 if (client->usesasl) { 01693 if (client->usetls && !aji_is_secure(client)) { 01694 break; 01695 } 01696 if (client->authorized) { 01697 if (features & IKS_STREAM_BIND) { 01698 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); 01699 auth = iks_make_resource_bind(client->jid); 01700 if (auth) { 01701 iks_insert_attrib(auth, "id", client->mid); 01702 ast_aji_increment_mid(client->mid); 01703 ast_aji_send(client, auth); 01704 iks_delete(auth); 01705 } else { 01706 ast_log(LOG_ERROR, "Out of memory.\n"); 01707 break; 01708 } 01709 } 01710 if (features & IKS_STREAM_SESSION) { 01711 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); 01712 auth = iks_make_session(); 01713 if (auth) { 01714 iks_insert_attrib(auth, "id", "auth"); 01715 ast_aji_increment_mid(client->mid); 01716 ast_aji_send(client, auth); 01717 iks_delete(auth); 01718 } else { 01719 ast_log(LOG_ERROR, "Out of memory.\n"); 01720 } 01721 } 01722 } else { 01723 int ret; 01724 if (!client->jid->user) { 01725 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 01726 break; 01727 } 01728 01729 ret = aji_start_sasl(client, features, client->jid->user, client->password); 01730 if (ret != IKS_OK) { 01731 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01732 return IKS_HOOK; 01733 } 01734 break; 01735 } 01736 } 01737 } else if (!strcmp("failure", iks_name(node))) { 01738 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 01739 } else if (!strcmp("success", iks_name(node))) { 01740 client->authorized = 1; 01741 aji_send_header(client, client->jid->server); 01742 } 01743 break; 01744 case IKS_NODE_ERROR: 01745 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01746 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01747 return IKS_HOOK; 01748 break; 01749 case IKS_NODE_STOP: 01750 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01751 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01752 return IKS_HOOK; 01753 break; 01754 } 01755 } else if (client->state != AJI_CONNECTED && client->component) { 01756 switch (type) { 01757 case IKS_NODE_START: 01758 if (client->state == AJI_DISCONNECTED) { 01759 char secret[160], shasum[320], *handshake; 01760 01761 sprintf(secret, "%s%s", pak->id, client->password); 01762 ast_sha1_hash(shasum, secret); 01763 handshake = NULL; 01764 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01765 aji_send_raw(client, handshake); 01766 ast_free(handshake); 01767 handshake = NULL; 01768 } 01769 client->state = AJI_CONNECTING; 01770 if (aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01771 client->state = AJI_CONNECTED; 01772 else 01773 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01774 break; 01775 } 01776 break; 01777 01778 case IKS_NODE_NORMAL: 01779 break; 01780 01781 case IKS_NODE_ERROR: 01782 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01783 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01784 return IKS_HOOK; 01785 01786 case IKS_NODE_STOP: 01787 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01788 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01789 return IKS_HOOK; 01790 } 01791 } 01792 01793 switch (pak->type) { 01794 case IKS_PAK_NONE: 01795 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01796 break; 01797 case IKS_PAK_MESSAGE: 01798 aji_handle_message(client, pak); 01799 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01800 break; 01801 case IKS_PAK_PRESENCE: 01802 aji_handle_presence(client, pak); 01803 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01804 break; 01805 case IKS_PAK_S10N: 01806 aji_handle_subscribe(client, pak); 01807 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01808 break; 01809 case IKS_PAK_IQ: 01810 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01811 aji_handle_iq(client, node); 01812 break; 01813 default: 01814 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01815 break; 01816 } 01817 01818 iks_filter_packet(client->f, pak); 01819 01820 if (node) 01821 iks_delete(node); 01822 01823 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01824 return IKS_OK; 01825 }
| static iks * aji_build_node_config | ( | iks * | pubsub, | |
| const char * | node_type, | |||
| const char * | collection_name | |||
| ) | [static] |
Definition at line 3871 of file res_jabber.c.
Referenced by aji_create_pubsub_node().
03872 { 03873 iks *configure, *x, *field_owner, *field_node_type, *field_node_config, 03874 *field_deliver_payload, *field_persist_items, *field_access_model, 03875 *field_pubsub_collection; 03876 configure = iks_insert(pubsub, "configure"); 03877 x = iks_insert(configure, "x"); 03878 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03879 iks_insert_attrib(x, "type", "submit"); 03880 field_owner = iks_insert(x, "field"); 03881 iks_insert_attrib(field_owner, "var", "FORM_TYPE"); 03882 iks_insert_attrib(field_owner, "type", "hidden"); 03883 iks_insert_cdata(iks_insert(field_owner, "value"), 03884 "http://jabber.org/protocol/pubsub#owner", 39); 03885 if (node_type) { 03886 field_node_type = iks_insert(x, "field"); 03887 iks_insert_attrib(field_node_type, "var", "pubsub#node_type"); 03888 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type)); 03889 } 03890 field_node_config = iks_insert(x, "field"); 03891 iks_insert_attrib(field_node_config, "var", "FORM_TYPE"); 03892 iks_insert_attrib(field_node_config, "type", "hidden"); 03893 iks_insert_cdata(iks_insert(field_node_config, "value"), 03894 "http://jabber.org/protocol/pubsub#node_config", 45); 03895 field_deliver_payload = iks_insert(x, "field"); 03896 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads"); 03897 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1); 03898 field_persist_items = iks_insert(x, "field"); 03899 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items"); 03900 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1); 03901 field_access_model = iks_insert(x, "field"); 03902 iks_insert_attrib(field_access_model, "var", "pubsub#access_model"); 03903 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9); 03904 if (node_type && !strcasecmp(node_type, "leaf")) { 03905 field_pubsub_collection = iks_insert(x, "field"); 03906 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection"); 03907 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name, 03908 strlen(collection_name)); 03909 } 03910 return configure; 03911 }
| static iks * aji_build_node_request | ( | struct aji_client * | client, | |
| const char * | collection | |||
| ) | [static] |
Build the a node request.
| client | the configured XMPP client we use to connect to a XMPP server | |
| collection | name of the collection for request |
Definition at line 3601 of file res_jabber.c.
References aji_pubsub_iq_create().
Referenced by aji_pubsub_purge_nodes(), and aji_request_pubsub_nodes().
03602 { 03603 iks *request = aji_pubsub_iq_create(client, "get"); 03604 iks *query; 03605 query = iks_insert(request, "query"); 03606 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 03607 if (collection) { 03608 iks_insert_attrib(query, "node", collection); 03609 } 03610 return request; 03611 }
| static iks * aji_build_publish_skeleton | ( | struct aji_client * | client, | |
| const char * | node, | |||
| const char * | event_type | |||
| ) | [static] |
Build the skeleton of a publish.
| client | the configured XMPP client we use to connect to a XMPP server | |
| node | Name of the node that will be published to | |
| event_type |
Definition at line 3429 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_test_flag, and publish.
Referenced by aji_publish_device_state(), and aji_publish_mwi().
03431 { 03432 iks *request = aji_pubsub_iq_create(client, "set"); 03433 iks *pubsub, *publish, *item; 03434 pubsub = iks_insert(request, "pubsub"); 03435 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03436 publish = iks_insert(pubsub, "publish"); 03437 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03438 iks_insert_attrib(publish, "node", node); 03439 } else { 03440 iks_insert_attrib(publish, "node", event_type); 03441 } 03442 item = iks_insert(publish, "item"); 03443 iks_insert_attrib(item, "id", node); 03444 return item; 03445 03446 }
| static char * aji_cli_create_collection | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Method to expose PubSub collection node creation via CLI.
Definition at line 3919 of file res_jabber.c.
References aji_create_pubsub_collection(), ast_cli_args::argc, ast_cli_args::argv, ast_aji_client_destroy(), ast_cli(), ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03920 { 03921 struct aji_client *client; 03922 const char *name; 03923 const char *collection_name; 03924 03925 switch (cmd) { 03926 case CLI_INIT: 03927 e->command = "jabber create collection"; 03928 e->usage = 03929 "Usage: jabber create collection <connection> <collection>\n" 03930 " Creates a PubSub collection node using the account\n" 03931 " as configured in jabber.conf.\n"; 03932 return NULL; 03933 case CLI_GENERATE: 03934 return NULL; 03935 } 03936 03937 if (a->argc != 5) { 03938 return CLI_SHOWUSAGE; 03939 } 03940 name = a->argv[3]; 03941 collection_name = a->argv[4]; 03942 03943 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03944 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03945 return CLI_FAILURE; 03946 } 03947 03948 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03949 aji_create_pubsub_collection(client, collection_name); 03950 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03951 return CLI_SUCCESS; 03952 }
| static char * aji_cli_create_leafnode | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Method to expose PubSub leaf node creation via CLI.
Definition at line 3958 of file res_jabber.c.
References aji_create_pubsub_leaf(), ast_cli_args::argc, ast_cli_args::argv, ast_aji_client_destroy(), ast_cli(), ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03959 { 03960 struct aji_client *client; 03961 const char *name; 03962 const char *collection_name; 03963 const char *leaf_name; 03964 03965 switch (cmd) { 03966 case CLI_INIT: 03967 e->command = "jabber create leaf"; 03968 e->usage = 03969 "Usage: jabber create leaf <connection> <collection> <leaf>\n" 03970 " Creates a PubSub leaf node using the account\n" 03971 " as configured in jabber.conf.\n"; 03972 return NULL; 03973 case CLI_GENERATE: 03974 return NULL; 03975 } 03976 03977 if (a->argc != 6) { 03978 return CLI_SHOWUSAGE; 03979 } 03980 name = a->argv[3]; 03981 collection_name = a->argv[4]; 03982 leaf_name = a->argv[5]; 03983 03984 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03985 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03986 return CLI_FAILURE; 03987 } 03988 03989 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03990 aji_create_pubsub_leaf(client, collection_name, leaf_name); 03991 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03992 return CLI_SUCCESS; 03993 }
| static char * aji_cli_delete_pubsub_node | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Method to expose PubSub node deletion via CLI.
| e | pointer to ast_cli_entry structure | |
| cmd | ||
| a | pointer to ast_cli_args structure |
Definition at line 3772 of file res_jabber.c.
References aji_delete_pubsub_node(), ast_cli_args::argc, ast_cli_args::argv, ast_aji_client_destroy(), ast_cli(), ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03774 { 03775 struct aji_client *client; 03776 const char *name; 03777 03778 switch (cmd) { 03779 case CLI_INIT: 03780 e->command = "jabber delete node"; 03781 e->usage = 03782 "Usage: jabber delete node <connection> <node>\n" 03783 " Deletes a node on PubSub server\n" 03784 " as configured in jabber.conf.\n"; 03785 return NULL; 03786 case CLI_GENERATE: 03787 return NULL; 03788 } 03789 03790 if (a->argc != 5) { 03791 return CLI_SHOWUSAGE; 03792 } 03793 name = a->argv[3]; 03794 03795 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03796 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03797 return CLI_FAILURE; 03798 } 03799 aji_delete_pubsub_node(client, a->argv[4]); 03800 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03801 return CLI_SUCCESS; 03802 }
| static char * aji_cli_list_pubsub_nodes | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Method to expose PubSub node list via CLI.
| e | pointer to ast_cli_entry structure | |
| cmd | ||
| a | pointer to ast_cli_args structure |
Definition at line 3647 of file res_jabber.c.
References aji_request_pubsub_nodes(), ast_cli_args::argc, ast_cli_args::argv, ast_aji_client_destroy(), ast_cli(), ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03649 { 03650 struct aji_client *client; 03651 const char *name = NULL; 03652 const char *collection = NULL; 03653 03654 switch (cmd) { 03655 case CLI_INIT: 03656 e->command = "jabber list nodes"; 03657 e->usage = 03658 "Usage: jabber list nodes <connection> [collection]\n" 03659 " Lists the user's nodes on the respective connection\n" 03660 " ([connection] as configured in jabber.conf.)\n"; 03661 return NULL; 03662 case CLI_GENERATE: 03663 return NULL; 03664 } 03665 03666 if (a->argc > 5 || a->argc < 4) { 03667 return CLI_SHOWUSAGE; 03668 } else if (a->argc == 4 || a->argc == 5) { 03669 name = a->argv[3]; 03670 } 03671 if (a->argc == 5) { 03672 collection = a->argv[4]; 03673 } 03674 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03675 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03676 return CLI_FAILURE; 03677 } 03678 03679 ast_cli(a->fd, "Listing pubsub nodes.\n"); 03680 aji_request_pubsub_nodes(client, collection); 03681 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03682 return CLI_SUCCESS; 03683 }
| static char * aji_cli_purge_pubsub_nodes | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Method to purge PubSub nodes via CLI.
| e | pointer to ast_cli_entry structure | |
| cmd | ||
| a | pointer to ast_cli_args structure |
Definition at line 3692 of file res_jabber.c.
References aji_delete_pubsub_node(), aji_pubsub_purge_nodes(), AJI_XEP0248, ast_cli_args::argc, ast_cli_args::argv, ast_aji_client_destroy(), ast_cli(), ast_test_flag, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03694 { 03695 struct aji_client *client; 03696 const char *name; 03697 03698 switch (cmd) { 03699 case CLI_INIT: 03700 e->command = "jabber purge nodes"; 03701 e->usage = 03702 "Usage: jabber purge nodes <connection> <node>\n" 03703 " Purges nodes on PubSub server\n" 03704 " as configured in jabber.conf.\n"; 03705 return NULL; 03706 case CLI_GENERATE: 03707 return NULL; 03708 } 03709 03710 if (a->argc != 5) { 03711 return CLI_SHOWUSAGE; 03712 } 03713 name = a->argv[3]; 03714 03715 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03716 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03717 return CLI_FAILURE; 03718 } 03719 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03720 aji_pubsub_purge_nodes(client, a->argv[4]); 03721 } else { 03722 aji_delete_pubsub_node(client, a->argv[4]); 03723 } 03724 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03725 return CLI_SUCCESS; 03726 }
| static int aji_client_connect | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 3138 of file res_jabber.c.
References AJI_CONNECTING, AJI_DISCONNECTED, aji_filter_roster(), aji_get_roster(), aji_init_event_distribution(), ast_aji_client_destroy(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::component, aji_client::distribute_events, aji_client::f, aji_client::jid, LOG_ERROR, aji_client::stack, and aji_client::state.
Referenced by aji_act_hook().
03139 { 03140 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03141 int res = IKS_FILTER_PASS; 03142 03143 if (client) { 03144 if (client->state == AJI_DISCONNECTED) { 03145 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); 03146 client->state = AJI_CONNECTING; 03147 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 03148 if (!client->component) { /*client*/ 03149 aji_get_roster(client); 03150 } 03151 if (client->distribute_events) { 03152 aji_init_event_distribution(client); 03153 } 03154 03155 iks_filter_remove_hook(client->f, aji_client_connect); 03156 /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ 03157 res = IKS_FILTER_EAT; 03158 } 03159 } else { 03160 ast_log(LOG_ERROR, "Out of memory.\n"); 03161 } 03162 03163 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03164 return res; 03165 }
| static int aji_client_info_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2046 of file res_jabber.c.
References aji_find_resource(), ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, aji_resource::cap, aji_client::jid, aji_version::jingle, LOG_ERROR, LOG_NOTICE, and aji_resource::resource.
Referenced by aji_create_client().
02047 { 02048 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02049 struct aji_resource *resource = NULL; 02050 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02051 02052 resource = aji_find_resource(buddy, pak->from->resource); 02053 if (pak->subtype == IKS_TYPE_RESULT) { 02054 if (!resource) { 02055 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02056 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02057 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02058 return IKS_FILTER_EAT; 02059 } 02060 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02061 resource->cap->jingle = 1; 02062 } else { 02063 resource->cap->jingle = 0; 02064 } 02065 } else if (pak->subtype == IKS_TYPE_GET) { 02066 iks *iq, *disco, *ident, *google, *query; 02067 iq = iks_new("iq"); 02068 query = iks_new("query"); 02069 ident = iks_new("identity"); 02070 disco = iks_new("feature"); 02071 google = iks_new("feature"); 02072 if (iq && ident && disco && google) { 02073 iks_insert_attrib(iq, "from", client->jid->full); 02074 iks_insert_attrib(iq, "to", pak->from->full); 02075 iks_insert_attrib(iq, "type", "result"); 02076 iks_insert_attrib(iq, "id", pak->id); 02077 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02078 iks_insert_attrib(ident, "category", "client"); 02079 iks_insert_attrib(ident, "type", "pc"); 02080 iks_insert_attrib(ident, "name", "asterisk"); 02081 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 02082 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 02083 iks_insert_node(iq, query); 02084 iks_insert_node(query, ident); 02085 iks_insert_node(query, google); 02086 iks_insert_node(query, disco); 02087 ast_aji_send(client, iq); 02088 } else { 02089 ast_log(LOG_ERROR, "Out of Memory.\n"); 02090 } 02091 02092 iks_delete(iq); 02093 iks_delete(query); 02094 iks_delete(ident); 02095 iks_delete(google); 02096 iks_delete(disco); 02097 } else if (pak->subtype == IKS_TYPE_ERROR) { 02098 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 02099 } 02100 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02101 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02102 return IKS_FILTER_EAT; 02103 }
| static void aji_create_affiliations | ( | struct aji_client * | client, | |
| const char * | node | |||
| ) | [static] |
Add Owner affiliations for pubsub node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| node | the name of the node to which to add affiliations |
Definition at line 3365 of file res_jabber.c.
References aji_pubsub_iq_create(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and aji_client::buddies.
Referenced by aji_create_pubsub_node().
03366 { 03367 iks *modify_affiliates = aji_pubsub_iq_create(client, "set"); 03368 iks *pubsub, *affiliations, *affiliate; 03369 pubsub = iks_insert(modify_affiliates, "pubsub"); 03370 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03371 affiliations = iks_insert(pubsub, "affiliations"); 03372 iks_insert_attrib(affiliations, "node", node); 03373 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03374 ASTOBJ_RDLOCK(iterator); 03375 affiliate = iks_insert(affiliations, "affiliation"); 03376 iks_insert_attrib(affiliate, "jid", iterator->name); 03377 iks_insert_attrib(affiliate, "affiliation", "owner"); 03378 ASTOBJ_UNLOCK(iterator); 03379 }); 03380 ast_aji_send(client, modify_affiliates); 03381 iks_delete(modify_affiliates); 03382 }
| static int aji_create_buddy | ( | char * | label, | |
| struct aji_client * | client | |||
| ) | [static] |
load config file.
Definition at line 4575 of file res_jabber.c.
References ast_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 4314 of file res_jabber.c.
References aji_act_hook(), AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), AJI_PUBSUB, aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_aji_client_destroy(), ast_calloc, ast_clear_flag, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, ast_free, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_set_flag, ast_test_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::context, aji_client::debug, aji_client::distribute_events, aji_client::f, aji_client::flags, aji_client::forcessl, aji_client::jid, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, ast_variable::name, aji_client::name, aji_client::name_space, ast_variable::next, aji_client::p, aji_client::password, aji_client::port, aji_client::priority, aji_client::pubsub_node, aji_client::send_to_dialplan, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and ast_variable::value.
Referenced by aji_load_config().
04315 { 04316 char *resource; 04317 struct aji_client *client = NULL; 04318 int flag = 0; 04319 04320 client = ASTOBJ_CONTAINER_FIND(&clients, label); 04321 if (!client) { 04322 flag = 1; 04323 client = ast_calloc(1, sizeof(*client)); 04324 if (!client) { 04325 ast_log(LOG_ERROR, "Out of memory!\n"); 04326 return 0; 04327 } 04328 ASTOBJ_INIT(client); 04329 ASTOBJ_WRLOCK(client); 04330 ASTOBJ_CONTAINER_INIT(&client->buddies); 04331 } else { 04332 ASTOBJ_WRLOCK(client); 04333 ASTOBJ_UNMARK(client); 04334 } 04335 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 04336 ast_copy_string(client->name, label, sizeof(client->name)); 04337 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 04338 ast_copy_string(client->context, "default", sizeof(client->context)); 04339 04340 /* Set default values for the client object */ 04341 client->debug = debug; 04342 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 04343 client->port = 5222; 04344 client->usetls = 1; 04345 client->usesasl = 1; 04346 client->forcessl = 0; 04347 client->keepalive = 1; 04348 client->timeout = 50; 04349 client->message_timeout = 5; 04350 client->distribute_events = 0; 04351 AST_LIST_HEAD_INIT(&client->messages); 04352 client->component = 0; 04353 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 04354 client->priority = 0; 04355 client->status = IKS_SHOW_AVAILABLE; 04356 client->send_to_dialplan = 0; 04357 04358 if (flag) { 04359 client->authorized = 0; 04360 client->state = AJI_DISCONNECTED; 04361 } 04362 while (var) { 04363 if (!strcasecmp(var->name, "username")) { 04364 ast_copy_string(client->user, var->value, sizeof(client->user)); 04365 } else if (!strcasecmp(var->name, "serverhost")) { 04366 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 04367 } else if (!strcasecmp(var->name, "secret")) { 04368 ast_copy_string(client->password, var->value, sizeof(client->password)); 04369 } else if (!strcasecmp(var->name, "statusmessage")) { 04370 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 04371 } else if (!strcasecmp(var->name, "port")) { 04372 client->port = atoi(var->value); 04373 } else if (!strcasecmp(var->name, "timeout")) { 04374 client->message_timeout = atoi(var->value); 04375 } else if (!strcasecmp(var->name, "debug")) { 04376 client->debug = (ast_false(var->value)) ? 0 : 1; 04377 } else if (!strcasecmp(var->name, "type")) { 04378 if (!strcasecmp(var->value, "component")) { 04379 client->component = 1; 04380 if (client->distribute_events) { 04381 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04382 client->distribute_events = 0; 04383 } 04384 } 04385 } else if (!strcasecmp(var->name, "distribute_events")) { 04386 if (ast_true(var->value)) { 04387 if (client->component) { 04388 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04389 } else { 04390 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) { 04391 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n"); 04392 } else { 04393 ast_set_flag(&pubsubflags, AJI_PUBSUB); 04394 client->distribute_events = 1; 04395 } 04396 } 04397 } 04398 } else if (!strcasecmp(var->name, "pubsub_node")) { 04399 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node)); 04400 } else if (!strcasecmp(var->name, "usetls")) { 04401 client->usetls = (ast_false(var->value)) ? 0 : 1; 04402 } else if (!strcasecmp(var->name, "usesasl")) { 04403 client->usesasl = (ast_false(var->value)) ? 0 : 1; 04404 } else if (!strcasecmp(var->name, "forceoldssl")) { 04405 client->forcessl = (ast_false(var->value)) ? 0 : 1; 04406 } else if (!strcasecmp(var->name, "keepalive")) { 04407 client->keepalive = (ast_false(var->value)) ? 0 : 1; 04408 } else if (!strcasecmp(var->name, "autoprune")) { 04409 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 04410 } else if (!strcasecmp(var->name, "autoregister")) { 04411 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 04412 } else if (!strcasecmp(var->name, "auth_policy")) { 04413 if (!strcasecmp(var->value, "accept")) { 04414 ast_set_flag(&client->flags, AJI_AUTOACCEPT); 04415 } else { 04416 ast_clear_flag(&client->flags, AJI_AUTOACCEPT); 04417 } 04418 } else if (!strcasecmp(var->name, "buddy")) { 04419 aji_create_buddy((char *)var->value, client); 04420 } else if (!strcasecmp(var->name, "priority")) { 04421 client->priority = atoi(var->value); 04422 } else if (!strcasecmp(var->name, "status")) { 04423 if (!strcasecmp(var->value, "unavailable")) { 04424 client->status = IKS_SHOW_UNAVAILABLE; 04425 } else if (!strcasecmp(var->value, "available") 04426 || !strcasecmp(var->value, "online")) { 04427 client->status = IKS_SHOW_AVAILABLE; 04428 } else if (!strcasecmp(var->value, "chat") 04429 || !strcasecmp(var->value, "chatty")) { 04430 client->status = IKS_SHOW_CHAT; 04431 } else if (!strcasecmp(var->value, "away")) { 04432 client->status = IKS_SHOW_AWAY; 04433 } else if (!strcasecmp(var->value, "xa") 04434 || !strcasecmp(var->value, "xaway")) { 04435 client->status = IKS_SHOW_XA; 04436 } else if (!strcasecmp(var->value, "dnd")) { 04437 client->status = IKS_SHOW_DND; 04438 } else if (!strcasecmp(var->value, "invisible")) { 04439 #ifdef IKS_SHOW_INVISIBLE 04440 client->status = IKS_SHOW_INVISIBLE; 04441 #else 04442 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 04443 client->status = IKS_SHOW_DND; 04444 #endif 04445 } else { 04446 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 04447 } 04448 } else if (!strcasecmp(var->name, "context")) { 04449 ast_copy_string(client->context, var->value, sizeof(client->context)); 04450 } else if (!strcasecmp(var->name, "sendtodialplan")) { 04451 client->send_to_dialplan = ast_true(var->value) ? 1 : 0; 04452 } 04453 /* no transport support in this version */ 04454 /* else if (!strcasecmp(var->name, "transport")) 04455 aji_create_transport(var->value, client); 04456 */ 04457 var = var->next; 04458 } 04459 if (!flag) { 04460 ASTOBJ_UNLOCK(client); 04461 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04462 return 1; 04463 } 04464 04465 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 04466 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 04467 if (!client->p) { 04468 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 04469 return 0; 04470 } 04471 client->stack = iks_stack_new(8192, 8192); 04472 if (!client->stack) { 04473 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 04474 return 0; 04475 } 04476 client->f = iks_filter_new(); 04477 if (!client->f) { 04478 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 04479 return 0; 04480 } 04481 if (!strchr(client->user, '/') && !client->component) { /*client */ 04482 resource = NULL; 04483 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 04484 client->jid = iks_id_new(client->stack, resource); 04485 ast_free(resource); 04486 } 04487 } else { 04488 client->jid = iks_id_new(client->stack, client->user); 04489 } 04490 if (client->component) { 04491 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04492 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 04493 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); 04494 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); 04495 } else { 04496 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04497 } 04498 04499 iks_set_log_hook(client->p, aji_log_hook); 04500 ASTOBJ_UNLOCK(client); 04501 ASTOBJ_CONTAINER_LINK(&clients, client); 04502 return 1; 04503 }
| static void aji_create_pubsub_collection | ( | struct aji_client * | client, | |
| const char * | collection_name | |||
| ) | [static] |
Create a PubSub collection node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| collection_name | The name to use for this collection |
Definition at line 3827 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_collection(), and aji_handle_pubsub_error().
03829 { 03830 aji_create_pubsub_node(client, "collection", collection_name, NULL); 03831 }
| static void aji_create_pubsub_leaf | ( | struct aji_client * | client, | |
| const char * | collection_name, | |||
| const char * | leaf_name | |||
| ) | [static] |
Create a PubSub leaf node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| leaf_name | The name to use for this collection |
Definition at line 3840 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_leafnode(), and aji_handle_pubsub_error().
03842 { 03843 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name); 03844 }
| static iks * aji_create_pubsub_node | ( | struct aji_client * | client, | |
| const char * | node_type, | |||
| const char * | name, | |||
| const char * | collection_name | |||
| ) | [static] |
Create a pubsub node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| node_type | the type of node to create | |
| name | the name of the node to create |
Definition at line 3853 of file res_jabber.c.
References aji_build_node_config(), aji_create_affiliations(), aji_pubsub_iq_create(), and ast_aji_send().
Referenced by aji_create_pubsub_collection(), aji_create_pubsub_leaf(), aji_handle_pubsub_error(), and aji_publish_device_state().
03855 { 03856 iks *node = aji_pubsub_iq_create(client, "set"); 03857 iks *pubsub, *create; 03858 pubsub = iks_insert(node, "pubsub"); 03859 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03860 create = iks_insert(pubsub, "create"); 03861 iks_insert_attrib(create, "node", name); 03862 aji_build_node_config(pubsub, node_type, collection_name); 03863 ast_aji_send(client, node); 03864 aji_create_affiliations(client, name); 03865 iks_delete(node); 03866 return 0; 03867 }
| static int aji_delete_node_list | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Delete pubsub item lists.
| data | pointer to aji_client structure | |
| pak | response from pubsub diso::items query |
Definition at line 3745 of file res_jabber.c.
References aji_delete_pubsub_node(), ast_log(), ASTOBJ_REF, aji_client::jid, and LOG_WARNING.
Referenced by aji_pubsub_purge_nodes().
03746 { 03747 03748 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03749 iks *item = NULL; 03750 if (iks_has_children(pak->query)) { 03751 item = iks_first_tag(pak->query); 03752 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial, 03753 iks_find_attrib(item, "node")); 03754 while ((item = iks_next_tag(item))) { 03755 aji_delete_pubsub_node(client, iks_find_attrib(item, "node")); 03756 } 03757 } 03758 if (item) { 03759 iks_delete(item); 03760 } 03761 return IKS_FILTER_EAT; 03762 }
| static void aji_delete_pubsub_node | ( | struct aji_client * | client, | |
| const char * | node_name | |||
| ) | [static] |
Delete a PubSub node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| node_name | the name of the node to delete return void |
Definition at line 3810 of file res_jabber.c.
References aji_pubsub_iq_create(), and ast_aji_send().
Referenced by aji_cli_delete_pubsub_node(), aji_cli_purge_pubsub_nodes(), and aji_delete_node_list().
03811 { 03812 iks *request = aji_pubsub_iq_create(client, "set"); 03813 iks *pubsub, *delete; 03814 pubsub = iks_insert(request, "pubsub"); 03815 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03816 delete = iks_insert(pubsub, "delete"); 03817 iks_insert_attrib(delete, "node", node_name); 03818 ast_aji_send(client, request); 03819 }
| static void aji_devstate_cb | ( | const struct ast_event * | ast_event, | |
| void * | data | |||
| ) | [static] |
Callback function for device state events.
| ast_event | ||
| data | void pointer to ast_client structure |
Definition at line 3257 of file res_jabber.c.
References aji_publish_device_state(), ast_aji_client_destroy(), ast_debug, ast_devstate_str(), ast_eid_cmp(), ast_eid_default, ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ASTOBJ_REF, and ASTOBJ_UNREF.
Referenced by aji_init_event_distribution().
03258 { 03259 const char *device; 03260 const char *device_state; 03261 struct aji_client *client; 03262 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03263 { 03264 /* If the event didn't originate from this server, don't send it back out. */ 03265 ast_debug(1, "Returning here\n"); 03266 return; 03267 } 03268 03269 client = ASTOBJ_REF((struct aji_client *) data); 03270 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); 03271 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); 03272 aji_publish_device_state(client, device, device_state); 03273 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03274 }
| static int aji_dinfo_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2112 of file res_jabber.c.
References aji_find_resource(), ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, aji_resource::cap, commands, aji_version::jingle, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_resource::resource, aji_client::user, and version.
Referenced by aji_create_client().
02113 { 02114 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02115 char *node = NULL; 02116 struct aji_resource *resource = NULL; 02117 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02118 02119 if (pak->subtype == IKS_TYPE_ERROR) { 02120 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 02121 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02122 return IKS_FILTER_EAT; 02123 } 02124 resource = aji_find_resource(buddy, pak->from->resource); 02125 if (pak->subtype == IKS_TYPE_RESULT) { 02126 if (!resource) { 02127 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02128 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02129 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02130 return IKS_FILTER_EAT; 02131 } 02132 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02133 resource->cap->jingle = 1; 02134 } else { 02135 resource->cap->jingle = 0; 02136 } 02137 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 02138 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 02139 02140 iq = iks_new("iq"); 02141 query = iks_new("query"); 02142 identity = iks_new("identity"); 02143 disco = iks_new("feature"); 02144 reg = iks_new("feature"); 02145 commands = iks_new("feature"); 02146 gateway = iks_new("feature"); 02147 version = iks_new("feature"); 02148 vcard = iks_new("feature"); 02149 search = iks_new("feature"); 02150 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 02151 iks_insert_attrib(iq, "from", client->user); 02152 iks_insert_attrib(iq, "to", pak->from->full); 02153 iks_insert_attrib(iq, "id", pak->id); 02154 iks_insert_attrib(iq, "type", "result"); 02155 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02156 iks_insert_attrib(identity, "category", "gateway"); 02157 iks_insert_attrib(identity, "type", "pstn"); 02158 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 02159 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 02160 iks_insert_attrib(reg, "var", "jabber:iq:register"); 02161 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 02162 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 02163 iks_insert_attrib(version, "var", "jabber:iq:version"); 02164 iks_insert_attrib(vcard, "var", "vcard-temp"); 02165 iks_insert_attrib(search, "var", "jabber:iq:search"); 02166 02167 iks_insert_node(iq, query); 02168 iks_insert_node(query, identity); 02169 iks_insert_node(query, disco); 02170 iks_insert_node(query, reg); 02171 iks_insert_node(query, commands); 02172 iks_insert_node(query, gateway); 02173 iks_insert_node(query, version); 02174 iks_insert_node(query, vcard); 02175 iks_insert_node(query, search); 02176 ast_aji_send(client, iq); 02177 } else { 02178 ast_log(LOG_ERROR, "Out of memory.\n"); 02179 } 02180 02181 iks_delete(iq); 02182 iks_delete(query); 02183 iks_delete(identity); 02184 iks_delete(disco); 02185 iks_delete(reg); 02186 iks_delete(commands); 02187 iks_delete(gateway); 02188 iks_delete(version); 02189 iks_delete(vcard); 02190 iks_delete(search); 02191 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 02192 iks *iq, *query, *confirm; 02193 iq = iks_new("iq"); 02194 query = iks_new("query"); 02195 confirm = iks_new("item"); 02196 02197 if (iq && query && confirm && client) { 02198 iks_insert_attrib(iq, "from", client->user); 02199 iks_insert_attrib(iq, "to", pak->from->full); 02200 iks_insert_attrib(iq, "id", pak->id); 02201 iks_insert_attrib(iq, "type", "result"); 02202 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 02203 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 02204 iks_insert_attrib(confirm, "node", "confirmaccount"); 02205 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 02206 iks_insert_attrib(confirm, "jid", client->user); 02207 iks_insert_node(iq, query); 02208 iks_insert_node(query, confirm); 02209 ast_aji_send(client, iq); 02210 } else { 02211 ast_log(LOG_ERROR, "Out of memory.\n"); 02212 } 02213 02214 iks_delete(iq); 02215 iks_delete(query); 02216 iks_delete(confirm); 02217 02218 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 02219 iks *iq, *query, *feature; 02220 02221 iq = iks_new("iq"); 02222 query = iks_new("query"); 02223 feature = iks_new("feature"); 02224 02225 if (iq && query && feature && client) { 02226 iks_insert_attrib(iq, "from", client->user); 02227 iks_insert_attrib(iq, "to", pak->from->full); 02228 iks_insert_attrib(iq, "id", pak->id); 02229 iks_insert_attrib(iq, "type", "result"); 02230 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02231 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 02232 iks_insert_node(iq, query); 02233 iks_insert_node(query, feature); 02234 ast_aji_send(client, iq); 02235 } else { 02236 ast_log(LOG_ERROR, "Out of memory.\n"); 02237 } 02238 02239 iks_delete(iq); 02240 iks_delete(query); 02241 iks_delete(feature); 02242 } 02243 02244 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02245 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02246 return IKS_FILTER_EAT; 02247 }
| static int aji_ditems_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1949 of file res_jabber.c.
References ast_aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, and aji_client::user.
Referenced by aji_create_client().
01950 { 01951 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01952 char *node = NULL; 01953 01954 if (!(node = iks_find_attrib(pak->query, "node"))) { 01955 iks *iq = NULL, *query = NULL, *item = NULL; 01956 iq = iks_new("iq"); 01957 query = iks_new("query"); 01958 item = iks_new("item"); 01959 01960 if (iq && query && item) { 01961 iks_insert_attrib(iq, "from", client->user); 01962 iks_insert_attrib(iq, "to", pak->from->full); 01963 iks_insert_attrib(iq, "id", pak->id); 01964 iks_insert_attrib(iq, "type", "result"); 01965 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01966 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01967 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01968 iks_insert_attrib(item, "jid", client->user); 01969 01970 iks_insert_node(iq, query); 01971 iks_insert_node(query, item); 01972 ast_aji_send(client, iq); 01973 } else { 01974 ast_log(LOG_ERROR, "Out of memory.\n"); 01975 } 01976 01977 iks_delete(iq); 01978 iks_delete(query); 01979 iks_delete(item); 01980 01981 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01982 iks *iq, *query, *confirm; 01983 iq = iks_new("iq"); 01984 query = iks_new("query"); 01985 confirm = iks_new("item"); 01986 if (iq && query && confirm && client) { 01987 iks_insert_attrib(iq, "from", client->user); 01988 iks_insert_attrib(iq, "to", pak->from->full); 01989 iks_insert_attrib(iq, "id", pak->id); 01990 iks_insert_attrib(iq, "type", "result"); 01991 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01992 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01993 iks_insert_attrib(confirm, "node", "confirmaccount"); 01994 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01995 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01996 01997 iks_insert_node(iq, query); 01998 iks_insert_node(query, confirm); 01999 ast_aji_send(client, iq); 02000 } else { 02001 ast_log(LOG_ERROR, "Out of memory.\n"); 02002 } 02003 02004 iks_delete(iq); 02005 iks_delete(query); 02006 iks_delete(confirm); 02007 02008 } else if (!strcasecmp(node, "confirmaccount")) { 02009 iks *iq = NULL, *query = NULL, *feature = NULL; 02010 02011 iq = iks_new("iq"); 02012 query = iks_new("query"); 02013 feature = iks_new("feature"); 02014 02015 if (iq && query && feature && client) { 02016 iks_insert_attrib(iq, "from", client->user); 02017 iks_insert_attrib(iq, "to", pak->from->full); 02018 iks_insert_attrib(iq, "id", pak->id); 02019 iks_insert_attrib(iq, "type", "result"); 02020 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 02021 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 02022 iks_insert_node(iq, query); 02023 iks_insert_node(query, feature); 02024 ast_aji_send(client, iq); 02025 } else { 02026 ast_log(LOG_ERROR, "Out of memory.\n"); 02027 } 02028 02029 iks_delete(iq); 02030 iks_delete(query); 02031 iks_delete(feature); 02032 } 02033 02034 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02035 return IKS_FILTER_EAT; 02036 02037 }
| static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4132 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.
04133 { 04134 switch (cmd) { 04135 case CLI_INIT: 04136 e->command = "jabber reload"; 04137 e->usage = 04138 "Usage: jabber reload\n" 04139 " Reloads the Jabber module.\n"; 04140 return NULL; 04141 case CLI_GENERATE: 04142 return NULL; 04143 } 04144 04145 aji_reload(1); 04146 ast_cli(a->fd, "Jabber Reloaded.\n"); 04147 return CLI_SUCCESS; 04148 }
| static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4090 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.
04091 { 04092 switch (cmd) { 04093 case CLI_INIT: 04094 e->command = "jabber set debug {on|off}"; 04095 e->usage = 04096 "Usage: jabber set debug {on|off}\n" 04097 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 04098 return NULL; 04099 case CLI_GENERATE: 04100 return NULL; 04101 } 04102 04103 if (a->argc != e->args) { 04104 return CLI_SHOWUSAGE; 04105 } 04106 04107 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 04108 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04109 ASTOBJ_RDLOCK(iterator); 04110 iterator->debug = 1; 04111 ASTOBJ_UNLOCK(iterator); 04112 }); 04113 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 04114 return CLI_SUCCESS; 04115 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 04116 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04117 ASTOBJ_RDLOCK(iterator); 04118 iterator->debug = 0; 04119 ASTOBJ_UNLOCK(iterator); 04120 }); 04121 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 04122 return CLI_SUCCESS; 04123 } 04124 return CLI_SHOWUSAGE; /* defaults to invalid */ 04125 }
| static int aji_filter_roster | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 3001 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().
03002 { 03003 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03004 int flag = 0; 03005 iks *x = NULL; 03006 struct aji_buddy *buddy; 03007 03008 client->state = AJI_CONNECTED; 03009 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03010 ASTOBJ_RDLOCK(iterator); 03011 x = iks_child(pak->query); 03012 flag = 0; 03013 while (x) { 03014 if (!iks_strcmp(iks_name(x), "item")) { 03015 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 03016 flag = 1; 03017 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 03018 } 03019 } 03020 x = iks_next(x); 03021 } 03022 if (!flag) { 03023 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 03024 } 03025 iks_delete(x); 03026 03027 ASTOBJ_UNLOCK(iterator); 03028 }); 03029 03030 x = iks_child(pak->query); 03031 while (x) { 03032 flag = 0; 03033 if (iks_strcmp(iks_name(x), "item") == 0) { 03034 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03035 ASTOBJ_RDLOCK(iterator); 03036 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 03037 flag = 1; 03038 ASTOBJ_UNLOCK(iterator); 03039 }); 03040 03041 if (flag) { 03042 /* found buddy, don't create a new one */ 03043 x = iks_next(x); 03044 continue; 03045 } 03046 03047 buddy = ast_calloc(1, sizeof(*buddy)); 03048 if (!buddy) { 03049 ast_log(LOG_WARNING, "Out of memory\n"); 03050 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03051 return 0; 03052 } 03053 ASTOBJ_INIT(buddy); 03054 ASTOBJ_WRLOCK(buddy); 03055 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 03056 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 03057 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 03058 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 03059 ASTOBJ_MARK(buddy); 03060 } else if (ast_test_flag(&client->flags, AJI_AUTOREGISTER)) { 03061 if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 03062 /* subscribe to buddy's presence only 03063 if we really need to */ 03064 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 03065 } 03066 } 03067 ASTOBJ_UNLOCK(buddy); 03068 if (buddy) { 03069 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 03070 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 03071 } 03072 } 03073 x = iks_next(x); 03074 } 03075 03076 iks_delete(x); 03077 aji_pruneregister(client); 03078 03079 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03080 return IKS_FILTER_EAT; 03081 }
| static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
| char * | name | |||
| ) | [static, read] |
Definition at line 554 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().
00555 { 00556 struct aji_resource *res = NULL; 00557 if (!buddy || !name) { 00558 return res; 00559 } 00560 res = buddy->resources; 00561 while (res) { 00562 if (!strcasecmp(res->resource, name)) { 00563 break; 00564 } 00565 res = res->next; 00566 } 00567 return res; 00568 }
| static struct aji_version* aji_find_version | ( | char * | node, | |
| char * | version, | |||
| ikspak * | pak | |||
| ) | [static, read] |
Definition at line 482 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().
00483 { 00484 struct aji_capabilities *list = NULL; 00485 struct aji_version *res = NULL; 00486 00487 list = capabilities; 00488 00489 if (!node) { 00490 node = pak->from->full; 00491 } 00492 if (!version) { 00493 version = "none supplied."; 00494 } 00495 while (list) { 00496 if (!strcasecmp(list->node, node)) { 00497 res = list->versions; 00498 while(res) { 00499 if (!strcasecmp(res->version, version)) { 00500 return res; 00501 } 00502 res = res->next; 00503 } 00504 /* Specified version not found. Let's add it to 00505 this node in our capabilities list */ 00506 if (!res) { 00507 res = ast_malloc(sizeof(*res)); 00508 if (!res) { 00509 ast_log(LOG_ERROR, "Out of memory!\n"); 00510 return NULL; 00511 } 00512 res->jingle = 0; 00513 res->parent = list; 00514 ast_copy_string(res->version, version, sizeof(res->version)); 00515 res->next = list->versions; 00516 list->versions = res; 00517 return res; 00518 } 00519 } 00520 list = list->next; 00521 } 00522 /* Specified node not found. Let's add it our capabilities list */ 00523 if (!list) { 00524 list = ast_malloc(sizeof(*list)); 00525 if (!list) { 00526 ast_log(LOG_ERROR, "Out of memory!\n"); 00527 return NULL; 00528 } 00529 res = ast_malloc(sizeof(*res)); 00530 if (!res) { 00531 ast_log(LOG_ERROR, "Out of memory!\n"); 00532 ast_free(list); 00533 return NULL; 00534 } 00535 ast_copy_string(list->node, node, sizeof(list->node)); 00536 ast_copy_string(res->version, version, sizeof(res->version)); 00537 res->jingle = 0; 00538 res->parent = list; 00539 res->next = NULL; 00540 list->versions = res; 00541 list->next = capabilities; 00542 capabilities = list; 00543 } 00544 return res; 00545 }
| static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Definition at line 3115 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().
03116 { 03117 iks *roster = NULL; 03118 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 03119 03120 if (roster) { 03121 iks_insert_attrib(roster, "id", "roster"); 03122 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 03123 ast_aji_send(client, roster); 03124 } 03125 03126 iks_delete(roster); 03127 03128 return 1; 03129 }
| 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 2268 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_msg_alloc(), ast_msg_destroy(), ast_msg_queue(), ast_msg_set_body(), ast_msg_set_context(), ast_msg_set_from(), ast_msg_set_to(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvnow(), aji_client::context, delete_old_messages(), aji_message::from, aji_message::id, LOG_ERROR, aji_message::message, aji_client::messages, aji_client::name, aji_client::send_to_dialplan, and aji_client::user.
Referenced by aji_act_hook().
02269 { 02270 struct aji_message *insert; 02271 int deleted = 0; 02272 struct ast_msg *msg; 02273 02274 ast_debug(3, "client %s received a message\n", client->name); 02275 02276 if (!(insert = ast_calloc(1, sizeof(*insert)))) { 02277 return; 02278 } 02279 02280 insert->arrived = ast_tvnow(); 02281 02282 /* wake up threads waiting for messages */ 02283 ast_mutex_lock(&messagelock); 02284 ast_cond_broadcast(&message_received_condition); 02285 ast_mutex_unlock(&messagelock); 02286 02287 if (iks_find_cdata(pak->x, "body")) { 02288 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 02289 } 02290 if (pak->id) { 02291 ast_copy_string(insert->id, pak->id, sizeof(insert->id)); 02292 } 02293 if (pak->from){ 02294 /* insert will furtherly be added to message list */ 02295 insert->from = ast_strdup(pak->from->full); 02296 if (!insert->from) { 02297 ast_log(LOG_ERROR, "Memory allocation failure\n"); 02298 return; 02299 } 02300 ast_debug(3, "message comes from %s\n", insert->from); 02301 } 02302 02303 if (client->send_to_dialplan) { 02304 if ((msg = ast_msg_alloc())) { 02305 int res; 02306 02307 res = ast_msg_set_to(msg, "xmpp:%s", client->user); 02308 res |= ast_msg_set_from(msg, "xmpp:%s", insert->from); 02309 res |= ast_msg_set_body(msg, "%s", insert->message); 02310 res |= ast_msg_set_context(msg, "%s", client->context); 02311 02312 if (res) { 02313 ast_msg_destroy(msg); 02314 } else { 02315 ast_msg_queue(msg); 02316 } 02317 02318 msg = NULL; 02319 } 02320 } 02321 02322 /* remove old messages received from this JID 02323 * and insert received message */ 02324 deleted = delete_old_messages(client, pak->from->partial); 02325 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 02326 AST_LIST_LOCK(&client->messages); 02327 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 02328 AST_LIST_UNLOCK(&client->messages); 02329 }
| static void aji_handle_presence | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2337 of file res_jabber.c.
References AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_buddy_destroy(), 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, EVENT_FLAG_USER, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, manager_event, aji_client::mid, aji_client::name, aji_resource::next, aji_resource::priority, aji_resource::resource, aji_buddy::resources, S_OR, aji_client::state, aji_resource::status, aji_client::status, status, aji_client::statusmessage, and type.
Referenced by aji_act_hook().
02338 { 02339 int status, priority; 02340 struct aji_buddy *buddy; 02341 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02342 char *ver, *node, *descrip, *type; 02343 02344 if (client->state != AJI_CONNECTED) 02345 aji_create_buddy(pak->from->partial, client); 02346 02347 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02348 if (!buddy && pak->from->partial) { 02349 /* allow our jid to be used to log in with another resource */ 02350 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02351 aji_create_buddy(pak->from->partial, client); 02352 else 02353 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02354 return; 02355 } 02356 type = iks_find_attrib(pak->x, "type"); 02357 if (client->component && type &&!strcasecmp("probe", type)) { 02358 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02359 ast_verbose("what i was looking for \n"); 02360 } 02361 ASTOBJ_WRLOCK(buddy); 02362 status = (pak->show) ? pak->show : 6; 02363 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02364 tmp = buddy->resources; 02365 descrip = ast_strdup(iks_find_cdata(pak->x, "status")); 02366 02367 while (tmp && pak->from->resource) { 02368 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02369 tmp->status = status; 02370 if (tmp->description) { 02371 ast_free(tmp->description); 02372 } 02373 tmp->description = descrip; 02374 found = tmp; 02375 if (status == 6) { /* Sign off Destroy resource */ 02376 if (last && found->next) { 02377 last->next = found->next; 02378 } else if (!last) { 02379 if (found->next) { 02380 buddy->resources = found->next; 02381 } else { 02382 buddy->resources = NULL; 02383 } 02384 } else if (!found->next) { 02385 if (last) { 02386 last->next = NULL; 02387 } else { 02388 buddy->resources = NULL; 02389 } 02390 } 02391 ast_free(found); 02392 found = NULL; 02393 break; 02394 } 02395 /* resource list is sorted by descending priority */ 02396 if (tmp->priority != priority) { 02397 found->priority = priority; 02398 if (!last && !found->next) { 02399 /* resource was found to be unique, 02400 leave loop */ 02401 break; 02402 } 02403 /* search for resource in our list 02404 and take it out for the moment */ 02405 if (last) { 02406 last->next = found->next; 02407 } else { 02408 buddy->resources = found->next; 02409 } 02410 02411 last = NULL; 02412 tmp = buddy->resources; 02413 if (!buddy->resources) { 02414 buddy->resources = found; 02415 } 02416 /* priority processing */ 02417 while (tmp) { 02418 /* insert resource back according to 02419 its priority value */ 02420 if (found->priority > tmp->priority) { 02421 if (last) { 02422 /* insert within list */ 02423 last->next = found; 02424 } 02425 found->next = tmp; 02426 if (!last) { 02427 /* insert on top */ 02428 buddy->resources = found; 02429 } 02430 break; 02431 } 02432 if (!tmp->next) { 02433 /* insert at the end of the list */ 02434 tmp->next = found; 02435 found->next = NULL; 02436 break; 02437 } 02438 last = tmp; 02439 tmp = tmp->next; 02440 } 02441 } 02442 break; 02443 } 02444 last = tmp; 02445 tmp = tmp->next; 02446 } 02447 02448 /* resource not found in our list, create it */ 02449 if (!found && status != 6 && pak->from->resource) { 02450 found = ast_calloc(1, sizeof(*found)); 02451 02452 if (!found) { 02453 ast_log(LOG_ERROR, "Out of memory!\n"); 02454 ASTOBJ_UNLOCK(buddy); 02455 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02456 return; 02457 } 02458 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02459 found->status = status; 02460 found->description = descrip; 02461 found->priority = priority; 02462 found->next = NULL; 02463 last = NULL; 02464 tmp = buddy->resources; 02465 while (tmp) { 02466 if (found->priority > tmp->priority) { 02467 if (last) { 02468 last->next = found; 02469 } 02470 found->next = tmp; 02471 if (!last) { 02472 buddy->resources = found; 02473 } 02474 break; 02475 } 02476 if (!tmp->next) { 02477 tmp->next = found; 02478 break; 02479 } 02480 last = tmp; 02481 tmp = tmp->next; 02482 } 02483 if (!tmp) { 02484 buddy->resources = found; 02485 } 02486 } 02487 02488 ASTOBJ_UNLOCK(buddy); 02489 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02490 02491 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02492 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02493 02494 /* handle gmail client's special caps:c tag */ 02495 if (!node && !ver) { 02496 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02497 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02498 } 02499 02500 /* retrieve capabilites of the new resource */ 02501 if (status != 6 && found && !found->cap) { 02502 found->cap = aji_find_version(node, ver, pak); 02503 if (gtalk_yuck(pak->x)) { /* gtalk should do discover */ 02504 found->cap->jingle = 1; 02505 } 02506 if (found->cap->jingle) { 02507 ast_debug(1, "Special case for google till they support discover.\n"); 02508 } else { 02509 iks *iq, *query; 02510 iq = iks_new("iq"); 02511 query = iks_new("query"); 02512 if (query && iq) { 02513 iks_insert_attrib(iq, "type", "get"); 02514 iks_insert_attrib(iq, "to", pak->from->full); 02515 iks_insert_attrib(iq, "from", client->jid->full); 02516 iks_insert_attrib(iq, "id", client->mid); 02517 ast_aji_increment_mid(client->mid); 02518 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02519 iks_insert_node(iq, query); 02520 ast_aji_send(client, iq); 02521 } else { 02522 ast_log(LOG_ERROR, "Out of memory.\n"); 02523 } 02524 iks_delete(query); 02525 iks_delete(iq); 02526 } 02527 } 02528 switch (pak->subtype) { 02529 case IKS_TYPE_AVAILABLE: 02530 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 02531 break; 02532 case IKS_TYPE_UNAVAILABLE: 02533 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 02534 break; 02535 default: 02536 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 02537 } 02538 switch (pak->show) { 02539 case IKS_SHOW_UNAVAILABLE: 02540 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02541 break; 02542 case IKS_SHOW_AVAILABLE: 02543 ast_debug(3, "JABBER: type is available\n"); 02544 break; 02545 case IKS_SHOW_CHAT: 02546 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02547 break; 02548 case IKS_SHOW_AWAY: 02549 ast_debug(3, "JABBER: type is away\n"); 02550 break; 02551 case IKS_SHOW_XA: 02552 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02553 break; 02554 case IKS_SHOW_DND: 02555 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02556 break; 02557 default: 02558 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 02559 } 02560 02561 if (found) { 02562 manager_event(EVENT_FLAG_USER, "JabberStatus", 02563 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 02564 "\r\nDescription: %s\r\n", 02565 client->name, pak->from->partial, found->resource, found->status, 02566 found->priority, S_OR(found->description, "")); 02567 } else { 02568 manager_event(EVENT_FLAG_USER, "JabberStatus", 02569 "Account: %s\r\nJID: %s\r\nStatus: %d\r\n", 02570 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE); 02571 } 02572 }
| static int aji_handle_pubsub_error | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 3520 of file res_jabber.c.
References aji_create_pubsub_collection(), aji_create_pubsub_leaf(), aji_create_pubsub_node(), aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_client_destroy(), ast_aji_send(), ast_log(), ast_test_flag, ASTOBJ_REF, ASTOBJ_UNREF, and LOG_ERROR.
Referenced by aji_init_event_distribution().
03521 { 03522 char *node_name; 03523 char *error; 03524 int error_num; 03525 iks *orig_request; 03526 iks *orig_pubsub = iks_find(pak->x, "pubsub"); 03527 struct aji_client *client; 03528 if (!orig_pubsub) { 03529 ast_log(LOG_ERROR, "Error isn't a PubSub error, why are we here?\n"); 03530 return IKS_FILTER_EAT; 03531 } 03532 orig_request = iks_child(orig_pubsub); 03533 error = iks_find_attrib(iks_find(pak->x, "error"), "code"); 03534 node_name = iks_find_attrib(orig_request, "node"); 03535 if (!sscanf(error, "%30d", &error_num)) { 03536 return IKS_FILTER_EAT; 03537 } 03538 if (error_num > 399 && error_num < 500 && error_num != 404) { 03539 ast_log(LOG_ERROR, 03540 "Error performing operation on PubSub node %s, %s.\n", node_name, error); 03541 return IKS_FILTER_EAT; 03542 } else if (error_num > 499 && error_num < 600) { 03543 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error); 03544 return IKS_FILTER_EAT; 03545 } 03546 03547 client = ASTOBJ_REF((struct aji_client *) data); 03548 03549 if (!strcasecmp(iks_name(orig_request), "publish")) { 03550 iks *request; 03551 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03552 if (iks_find(iks_find(orig_request, "item"), "state")) { 03553 aji_create_pubsub_leaf(client, "device_state", node_name); 03554 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) { 03555 aji_create_pubsub_leaf(client, "message_waiting", node_name); 03556 } 03557 } else { 03558 aji_create_pubsub_node(client, NULL, node_name, NULL); 03559 } 03560 request = aji_pubsub_iq_create(client, "set"); 03561 iks_insert_node(request, orig_pubsub); 03562 ast_aji_send(client, request); 03563 iks_delete(request); 03564 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03565 return IKS_FILTER_EAT; 03566 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) { 03567 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03568 aji_create_pubsub_collection(client, node_name); 03569 } else { 03570 aji_create_pubsub_node(client, NULL, node_name, NULL); 03571 } 03572 } 03573 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03574 return IKS_FILTER_EAT; 03575 }
| static int aji_handle_pubsub_event | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Callback for handling PubSub events.
| data | void pointer to aji_client structure |
Definition at line 3310 of file res_jabber.c.
References ast_debug, ast_devstate_val(), ast_eid_cmp(), ast_eid_default, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_RAW, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_log(), ast_str_to_eid(), context, LOG_ERROR, and strsep().
Referenced by aji_init_event_distribution().
03311 { 03312 char *item_id, *device_state, *context; 03313 int oldmsgs, newmsgs; 03314 iks *item, *item_content; 03315 struct ast_eid pubsub_eid; 03316 struct ast_event *event; 03317 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); 03318 if (!item) { 03319 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); 03320 return IKS_FILTER_EAT; 03321 } 03322 item_id = iks_find_attrib(item, "id"); 03323 item_content = iks_child(item); 03324 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid")); 03325 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) { 03326 ast_debug(1, "Returning here, eid of incoming event matches ours!\n"); 03327 return IKS_FILTER_EAT; 03328 } 03329 if (!strcasecmp(iks_name(item_content), "state")) { 03330 device_state = iks_find_cdata(item, "state"); 03331 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, 03332 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, 03333 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, 03334 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03335 AST_EVENT_IE_END))) { 03336 return IKS_FILTER_EAT; 03337 } 03338 } else if (!strcasecmp(iks_name(item_content), "mailbox")) { 03339 context = strsep(&item_id, "@"); 03340 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs); 03341 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs); 03342 if (!(event = ast_event_new(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX, 03343 AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_CONTEXT, 03344 AST_EVENT_IE_PLTYPE_STR, context, AST_EVENT_IE_OLDMSGS, 03345 AST_EVENT_IE_PLTYPE_UINT, oldmsgs, AST_EVENT_IE_NEWMSGS, 03346 AST_EVENT_IE_PLTYPE_UINT, newmsgs, AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, 03347 &pubsub_eid, sizeof(pubsub_eid), AST_EVENT_IE_END))) { 03348 return IKS_FILTER_EAT; 03349 } 03350 } else { 03351 ast_debug(1, "Don't know how to handle PubSub event of type %s\n", 03352 iks_name(item_content)); 03353 return IKS_FILTER_EAT; 03354 } 03355 ast_event_queue_and_cache(event); 03356 return IKS_FILTER_EAT; 03357 }
| static void aji_handle_subscribe | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2581 of file res_jabber.c.
References AJI_AUTOACCEPT, aji_create_buddy(), aji_set_presence(), ast_aji_buddy_destroy(), ast_aji_send(), ast_log(), ast_test_flag, ast_verb, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, aji_client::component, aji_client::flags, aji_client::jid, LOG_ERROR, aji_client::status, status, and aji_client::statusmessage.
Referenced by aji_act_hook().
02582 { 02583 iks *presence = NULL, *status = NULL; 02584 struct aji_buddy* buddy = NULL; 02585 02586 switch (pak->subtype) { 02587 case IKS_TYPE_SUBSCRIBE: 02588 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) { 02589 presence = iks_new("presence"); 02590 status = iks_new("status"); 02591 if (presence && status) { 02592 iks_insert_attrib(presence, "type", "subscribed"); 02593 iks_insert_attrib(presence, "to", pak->from->full); 02594 iks_insert_attrib(presence, "from", client->jid->full); 02595 if (pak->id) 02596 iks_insert_attrib(presence, "id", pak->id); 02597 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02598 iks_insert_node(presence, status); 02599 ast_aji_send(client, presence); 02600 } else { 02601 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02602 } 02603 02604 iks_delete(presence); 02605 iks_delete(status); 02606 } 02607 02608 if (client->component) 02609 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02610 case IKS_TYPE_SUBSCRIBED: 02611 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02612 if (!buddy && pak->from->partial) { 02613 aji_create_buddy(pak->from->partial, client); 02614 } else if (buddy) { 02615 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02616 } 02617 default: 02618 ast_verb(5, "JABBER: This is a subcription of type %i\n", pak->subtype); 02619 } 02620 }
| static void aji_init_event_distribution | ( | struct aji_client * | client | ) | [static] |
Initialize collections for event distribution.
| client | the configured XMPP client we use to connect to a XMPP server |
Definition at line 3281 of file res_jabber.c.
References aji_devstate_cb(), aji_handle_pubsub_error(), aji_handle_pubsub_event(), aji_mwi_cb(), aji_pubsub_subscribe(), ast_enable_distributed_devstate(), AST_EVENT_DEVICE_STATE_CHANGE, ast_event_dump_cache(), AST_EVENT_IE_END, AST_EVENT_MWI, ast_event_subscribe(), aji_client::f, and aji_client::pubsub_node.
Referenced by aji_client_connect(), and aji_reload().
03282 { 03283 if (!mwi_sub) { 03284 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription", 03285 client, AST_EVENT_IE_END); 03286 } 03287 if (!device_state_sub) { 03288 if (ast_enable_distributed_devstate()) { 03289 return; 03290 } 03291 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 03292 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END); 03293 ast_event_dump_cache(device_state_sub); 03294 } 03295 03296 aji_pubsub_subscribe(client, "device_state"); 03297 aji_pubsub_subscribe(client, "message_waiting"); 03298 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE, 03299 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE); 03300 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE, 03301 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE); 03302 03303 }
| static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 3173 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().
03174 { 03175 int connected = IKS_NET_NOCONN; 03176 03177 #ifdef HAVE_OPENSSL 03178 /* reset stream flags */ 03179 client->stream_flags = 0; 03180 #endif 03181 /* If it's a component, connect to user, otherwise, connect to server */ 03182 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 03183 03184 if (connected == IKS_NET_NOCONN) { 03185 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 03186 return IKS_HOOK; 03187 } else if (connected == IKS_NET_NODNS) { 03188 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, 03189 S_OR(client->serverhost, client->jid->server)); 03190 return IKS_HOOK; 03191 } 03192 03193 return IKS_OK; 03194 }
| static int aji_io_recv | ( | struct aji_client * | client, | |
| char * | buffer, | |||
| size_t | buf_len, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 1337 of file res_jabber.c.
References aji_is_secure(), ast_poll, len(), and aji_client::p.
Referenced by aji_recv().
01338 { 01339 struct pollfd pfd = { .events = POLLIN }; 01340 int len, res; 01341 01342 #ifdef HAVE_OPENSSL 01343 if (aji_is_secure(client)) { 01344 pfd.fd = SSL_get_fd(client->ssl_session); 01345 if (pfd.fd < 0) { 01346 return -1; 01347 } 01348 } else 01349 #endif /* HAVE_OPENSSL */ 01350 pfd.fd = iks_fd(client->p); 01351 01352 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1); 01353 if (res > 0) { 01354 #ifdef HAVE_OPENSSL 01355 if (aji_is_secure(client)) { 01356 len = SSL_read(client->ssl_session, buffer, buf_len); 01357 } else 01358 #endif /* HAVE_OPENSSL */ 01359 len = recv(pfd.fd, buffer, buf_len, 0); 01360 01361 if (len > 0) { 01362 return len; 01363 } else if (len <= 0) { 01364 return -1; 01365 } 01366 } 01367 return res; 01368 }
| static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Definition at line 1247 of file res_jabber.c.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
01248 { 01249 #ifdef HAVE_OPENSSL 01250 return client->stream_flags & SECURE; 01251 #else 01252 return 0; 01253 #endif 01254 }
| static int aji_join_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Application to join a chat room.
| chan | ast_channel | |
| data | Data is sender|jid|nickname. |
| 0 | success | |
| -1 | error |
Definition at line 999 of file res_jabber.c.
References AJI_MAX_RESJIDLEN, args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_join_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, aji_client::component, aji_client::jid, and LOG_ERROR.
Referenced by load_module().
01000 { 01001 struct aji_client *client = NULL; 01002 char *s; 01003 char nick[AJI_MAX_RESJIDLEN]; 01004 01005 AST_DECLARE_APP_ARGS(args, 01006 AST_APP_ARG(sender); 01007 AST_APP_ARG(jid); 01008 AST_APP_ARG(nick); 01009 ); 01010 01011 if (!data) { 01012 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01013 return -1; 01014 } 01015 s = ast_strdupa(data); 01016 01017 AST_STANDARD_APP_ARGS(args, s); 01018 if (args.argc < 2 || args.argc > 3) { 01019 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01020 return -1; 01021 } 01022 01023 if (strchr(args.jid, '/')) { 01024 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n"); 01025 return -1; 01026 } 01027 01028 if (!(client = ast_aji_get_client(args.sender))) { 01029 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01030 return -1; 01031 } 01032 01033 if (!ast_strlen_zero(args.nick)) { 01034 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01035 } else { 01036 if (client->component) { 01037 sprintf(nick, "asterisk"); 01038 } else { 01039 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01040 } 01041 } 01042 01043 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01044 ast_aji_join_chat(client, args.jid, nick); 01045 } else { 01046 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid); 01047 } 01048 01049 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01050 return 0; 01051 }
| static int aji_leave_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Application to leave a chat room.
| chan | ast_channel | |
| data | Data is sender|jid|nickname. |
| 0 | success | |
| -1 | error |
Definition at line 1060 of file res_jabber.c.
References AJI_MAX_RESJIDLEN, args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_leave_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, aji_client::component, aji_client::jid, and LOG_ERROR.
Referenced by load_module().
01061 { 01062 struct aji_client *client = NULL; 01063 char *s; 01064 char nick[AJI_MAX_RESJIDLEN]; 01065 AST_DECLARE_APP_ARGS(args, 01066 AST_APP_ARG(sender); 01067 AST_APP_ARG(jid); 01068 AST_APP_ARG(nick); 01069 ); 01070 01071 if (!data) { 01072 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01073 return -1; 01074 } 01075 s = ast_strdupa(data); 01076 01077 AST_STANDARD_APP_ARGS(args, s); 01078 if (args.argc < 2 || args.argc > 3) { 01079 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01080 return -1; 01081 } 01082 01083 if (strchr(args.jid, '/')) { 01084 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n"); 01085 return -1; 01086 } 01087 01088 if (!(client = ast_aji_get_client(args.sender))) { 01089 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01090 return -1; 01091 } 01092 01093 if (!ast_strlen_zero(args.nick)) { 01094 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01095 } else { 01096 if (client->component) { 01097 sprintf(nick, "asterisk"); 01098 } else { 01099 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01100 } 01101 } 01102 01103 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01104 ast_aji_leave_chat(client, args.jid, nick); 01105 } 01106 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01107 return 0; 01108 }
| static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 4602 of file res_jabber.c.
References AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), AJI_PUBSUB_AUTOCREATE, AJI_XEP0248, ast_category_browse(), ast_clear_flag, 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().
04603 { 04604 char *cat = NULL; 04605 int debug = 0; 04606 struct ast_config *cfg = NULL; 04607 struct ast_variable *var = NULL; 04608 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04609 04610 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 04611 return -1; 04612 } 04613 04614 /* Reset flags to default value */ 04615 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT); 04616 04617 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 04618 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 04619 return 0; 04620 } 04621 04622 cat = ast_category_browse(cfg, NULL); 04623 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 04624 if (!strcasecmp(var->name, "debug")) { 04625 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 04626 } else if (!strcasecmp(var->name, "autoprune")) { 04627 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 04628 } else if (!strcasecmp(var->name, "autoregister")) { 04629 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 04630 } else if (!strcasecmp(var->name, "collection_nodes")) { 04631 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248); 04632 } else if (!strcasecmp(var->name, "pubsub_autocreate")) { 04633 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE); 04634 } else if (!strcasecmp(var->name, "auth_policy")) { 04635 if (!strcasecmp(var->value, "accept")) { 04636 ast_set_flag(&globalflags, AJI_AUTOACCEPT); 04637 } else { 04638 ast_clear_flag(&globalflags, AJI_AUTOACCEPT); 04639 } 04640 } 04641 } 04642 04643 while (cat) { 04644 if (strcasecmp(cat, "general")) { 04645 var = ast_variable_browse(cfg, cat); 04646 aji_create_client(cat, var, debug); 04647 } 04648 cat = ast_category_browse(cfg, cat); 04649 } 04650 ast_config_destroy(cfg); /* or leak memory */ 04651 return 1; 04652 }
| static void aji_log_hook | ( | void * | data, | |
| const char * | xmpp, | |||
| size_t | size, | |||
| int | is_incoming | |||
| ) | [static] |
Definition at line 1528 of file res_jabber.c.
References ast_aji_client_destroy(), ast_strlen_zero(), ast_verbose, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::debug, EVENT_FLAG_USER, manager_event, aji_client::name, and option_debug.
Referenced by aji_create_client(), aji_recv(), and aji_send_raw().
01529 { 01530 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01531 01532 if (!ast_strlen_zero(xmpp)) { 01533 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 01534 } 01535 01536 if (client->debug) { 01537 if (is_incoming) { 01538 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 01539 } else { 01540 if (strlen(xmpp) == 1) { 01541 if (option_debug > 2 && xmpp[0] == ' ') { 01542 ast_verbose("\nJABBER: Keep alive packet\n"); 01543 } 01544 } else { 01545 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 01546 } 01547 } 01548 01549 } 01550 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01551 }
| static void aji_message_destroy | ( | struct aji_message * | obj | ) | [static] |
Definition at line 461 of file res_jabber.c.
References ast_free, aji_message::from, and aji_message::message.
Referenced by acf_jabberreceive_read(), ast_aji_client_destroy(), and delete_old_messages().
00462 { 00463 if (obj->from) { 00464 ast_free(obj->from); 00465 } 00466 if (obj->message) { 00467 ast_free(obj->message); 00468 } 00469 ast_free(obj); 00470 }
| static void aji_mwi_cb | ( | const struct ast_event * | ast_event, | |
| void * | data | |||
| ) | [static] |
Callback function for MWI events.
| ast_event | ||
| data | void pointer to ast_client structure |
Definition at line 3226 of file res_jabber.c.
References aji_publish_mwi(), ast_aji_client_destroy(), ast_debug, ast_eid_cmp(), ast_eid_default, ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EID, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, ASTOBJ_REF, ASTOBJ_UNREF, context, and mailbox.
Referenced by aji_init_event_distribution().
03227 { 03228 const char *mailbox; 03229 const char *context; 03230 char oldmsgs[10]; 03231 char newmsgs[10]; 03232 struct aji_client *client; 03233 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03234 { 03235 /* If the event didn't originate from this server, don't send it back out. */ 03236 ast_debug(1, "Returning here\n"); 03237 return; 03238 } 03239 03240 client = ASTOBJ_REF((struct aji_client *) data); 03241 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX); 03242 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT); 03243 snprintf(oldmsgs, sizeof(oldmsgs), "%d", 03244 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS)); 03245 snprintf(newmsgs, sizeof(newmsgs), "%d", 03246 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS)); 03247 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs); 03248 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03249 03250 }
| static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2947 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.
02948 { 02949 iks *removeiq = iks_new("iq"); 02950 iks *removequery = iks_new("query"); 02951 iks *removeitem = iks_new("item"); 02952 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02953 if (!client || !removeiq || !removequery || !removeitem || !send) { 02954 ast_log(LOG_ERROR, "Out of memory.\n"); 02955 goto safeout; 02956 } 02957 02958 iks_insert_node(removeiq, removequery); 02959 iks_insert_node(removequery, removeitem); 02960 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02961 ASTOBJ_RDLOCK(iterator); 02962 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02963 * be called at the same time */ 02964 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02965 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02966 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02967 " so I am no longer subscribing to your presence.\n")); 02968 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02969 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02970 " your access to my presence.\n")); 02971 iks_insert_attrib(removeiq, "from", client->jid->full); 02972 iks_insert_attrib(removeiq, "type", "set"); 02973 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02974 iks_insert_attrib(removeitem, "jid", iterator->name); 02975 iks_insert_attrib(removeitem, "subscription", "remove"); 02976 ast_aji_send(client, removeiq); 02977 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02978 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02979 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02980 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02981 } 02982 ASTOBJ_UNLOCK(iterator); 02983 }); 02984 02985 safeout: 02986 iks_delete(removeiq); 02987 iks_delete(removequery); 02988 iks_delete(removeitem); 02989 iks_delete(send); 02990 02991 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, ast_aji_buddy_destroy); 02992 }
| static void aji_publish_device_state | ( | struct aji_client * | client, | |
| const char * | device, | |||
| const char * | device_state | |||
| ) | [static] |
Publish device state to a PubSub node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| device | the name of the device whose state to publish | |
| device_state | the state to publish |
Definition at line 3455 of file res_jabber.c.
References aji_build_publish_skeleton(), aji_create_pubsub_node(), AJI_PUBSUB_AUTOCREATE, AJI_XEP0248, ast_aji_send(), ast_eid_default, ast_eid_to_str(), and ast_test_flag.
Referenced by aji_devstate_cb().
03457 { 03458 iks *request = aji_build_publish_skeleton(client, device, "device_state"); 03459 iks *state; 03460 char eid_str[20]; 03461 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { 03462 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03463 aji_create_pubsub_node(client, "leaf", device, "device_state"); 03464 } else { 03465 aji_create_pubsub_node(client, NULL, device, NULL); 03466 } 03467 } 03468 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03469 state = iks_insert(request, "state"); 03470 iks_insert_attrib(state, "xmlns", "http://asterisk.org"); 03471 iks_insert_attrib(state, "eid", eid_str); 03472 iks_insert_cdata(state, device_state, strlen(device_state)); 03473 ast_aji_send(client, iks_root(request)); 03474 iks_delete(request); 03475 }
| static void aji_publish_mwi | ( | struct aji_client * | client, | |
| const char * | mailbox, | |||
| const char * | context, | |||
| const char * | oldmsgs, | |||
| const char * | newmsgs | |||
| ) | [static] |
Publish MWI to a PubSub node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| device | the name of the device whose state to publish | |
| device_state | the state to publish |
Definition at line 3484 of file res_jabber.c.
References aji_build_publish_skeleton(), ast_aji_send(), ast_eid_default, ast_eid_to_str(), AST_MAX_CONTEXT, and AST_MAX_EXTENSION.
Referenced by aji_mwi_cb().
03486 { 03487 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT]; 03488 char eid_str[20]; 03489 iks *mailbox_node, *request; 03490 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); 03491 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting"); 03492 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03493 mailbox_node = iks_insert(request, "mailbox"); 03494 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org"); 03495 iks_insert_attrib(mailbox_node, "eid", eid_str); 03496 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs)); 03497 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs)); 03498 ast_aji_send(client, iks_root(request)); 03499 iks_delete(request); 03500 }
| static iks * aji_pubsub_iq_create | ( | struct aji_client * | client, | |
| const char * | type | |||
| ) | [static] |
Create an IQ packet.
| client | the configured XMPP client we use to connect to a XMPP server | |
| type | the type of IQ packet to create |
Definition at line 3508 of file res_jabber.c.
References ast_aji_increment_mid(), aji_client::jid, aji_client::mid, and aji_client::pubsub_node.
Referenced by aji_build_node_request(), aji_build_publish_skeleton(), aji_create_affiliations(), aji_create_pubsub_node(), aji_delete_pubsub_node(), aji_handle_pubsub_error(), and aji_pubsub_subscribe().
03509 { 03510 iks *request = iks_new("iq"); 03511 03512 iks_insert_attrib(request, "to", client->pubsub_node); 03513 iks_insert_attrib(request, "from", client->jid->full); 03514 iks_insert_attrib(request, "type", type); 03515 ast_aji_increment_mid(client->mid); 03516 iks_insert_attrib(request, "id", client->mid); 03517 return request; 03518 }
| static void aji_pubsub_purge_nodes | ( | struct aji_client * | client, | |
| const char * | collection_name | |||
| ) | [static] |
Definition at line 3728 of file res_jabber.c.
References aji_build_node_request(), aji_delete_node_list(), ast_aji_send(), aji_client::f, and aji_client::mid.
Referenced by aji_cli_purge_pubsub_nodes().
03729 { 03730 iks *request = aji_build_node_request(client, collection_name); 03731 ast_aji_send(client, request); 03732 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE, 03733 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03734 IKS_RULE_DONE); 03735 ast_aji_send(client, request); 03736 iks_delete(request); 03737 }
| static void aji_pubsub_subscribe | ( | struct aji_client * | client, | |
| const char * | node | |||
| ) | [static] |
Subscribe to a PubSub node.
| client | the configured XMPP client we use to connect to a XMPP server | |
| node | the name of the node to which to subscribe |
Definition at line 3390 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_send(), ast_test_flag, aji_client::jid, and subscribe.
Referenced by aji_init_event_distribution().
03391 { 03392 iks *request = aji_pubsub_iq_create(client, "set"); 03393 iks *pubsub, *subscribe; 03394 03395 pubsub = iks_insert(request, "pubsub"); 03396 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03397 subscribe = iks_insert(pubsub, "subscribe"); 03398 iks_insert_attrib(subscribe, "jid", client->jid->partial); 03399 iks_insert_attrib(subscribe, "node", node); 03400 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03401 iks *options, *x, *sub_options, *sub_type, *sub_depth; 03402 options = iks_insert(pubsub, "options"); 03403 x = iks_insert(options, "x"); 03404 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03405 iks_insert_attrib(x, "type", "submit"); 03406 sub_options = iks_insert(x, "field"); 03407 iks_insert_attrib(sub_options, "var", "FORM_TYPE"); 03408 iks_insert_attrib(sub_options, "type", "hidden"); 03409 iks_insert_cdata(iks_insert(sub_options, "value"), 03410 "http://jabber.org/protocol/pubsub#subscribe_options", 51); 03411 sub_type = iks_insert(x, "field"); 03412 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type"); 03413 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5); 03414 sub_depth = iks_insert(x, "field"); 03415 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth"); 03416 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3); 03417 } 03418 ast_aji_send(client, request); 03419 iks_delete(request); 03420 }
| static int aji_receive_node_list | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Receive pubsub item lists.
| data | pointer to aji_client structure | |
| pak | response from pubsub diso::items query |
Definition at line 3619 of file res_jabber.c.
References ast_aji_client_destroy(), ast_verbose, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::jid, and aji_client::name.
Referenced by aji_request_pubsub_nodes().
03620 { 03621 03622 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03623 iks *item = NULL; 03624 if (iks_has_children(pak->query)) { 03625 item = iks_first_tag(pak->query); 03626 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial, 03627 iks_find_attrib(item, "node")); 03628 while ((item = iks_next_tag(item))) { 03629 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node")); 03630 } 03631 } 03632 if (item) { 03633 iks_delete(item); 03634 } 03635 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03636 return IKS_FILTER_EAT; 03637 }
| static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 3089 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().
03090 { 03091 int res = 0; 03092 03093 if (client->state) { 03094 client->state = AJI_DISCONNECTED; 03095 } 03096 client->timeout = 50; 03097 if (client->p) { 03098 iks_parser_reset(client->p); 03099 } 03100 if (client->authorized) { 03101 client->authorized = 0; 03102 } 03103 03104 res = aji_initialize(client); 03105 03106 return res; 03107 }
| static int aji_recv | ( | struct aji_client * | client, | |
| int | timeout | |||
| ) | [static] |
Definition at line 1382 of file res_jabber.c.
References aji_io_recv(), aji_log_hook(), ast_debug, ast_log(), IKS_NET_EXPIRED, len(), LOG_WARNING, NET_IO_BUF_SIZE, and aji_client::p.
Referenced by aji_act_hook(), and aji_recv_loop().
01383 { 01384 int len, ret; 01385 char buf[NET_IO_BUF_SIZE - 1]; 01386 char newbuf[NET_IO_BUF_SIZE - 1]; 01387 int pos = 0; 01388 int newbufpos = 0; 01389 unsigned char c; 01390 01391 memset(buf, 0, sizeof(buf)); 01392 memset(newbuf, 0, sizeof(newbuf)); 01393 01394 while (1) { 01395 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 01396 if (len < 0) return IKS_NET_RWERR; 01397 if (len == 0) return IKS_NET_EXPIRED; 01398 buf[len] = '\0'; 01399 01400 /* our iksemel parser won't work as expected if we feed 01401 it with XML packets that contain multiple whitespace 01402 characters between tags */ 01403 while (pos < len) { 01404 c = buf[pos]; 01405 /* if we stumble on the ending tag character, 01406 we skip any whitespace that follows it*/ 01407 if (c == '>') { 01408 while (isspace(buf[pos+1])) { 01409 pos++; 01410 } 01411 } 01412 newbuf[newbufpos] = c; 01413 newbufpos ++; 01414 pos++; 01415 } 01416 pos = 0; 01417 newbufpos = 0; 01418 01419 /* Log the message here, because iksemel's logHook is 01420 unaccessible */ 01421 aji_log_hook(client, buf, len, 1); 01422 01423 /* let iksemel deal with the string length, 01424 and reset our buffer */ 01425 ret = iks_parse(client->p, newbuf, 0, 0); 01426 memset(newbuf, 0, sizeof(newbuf)); 01427 01428 switch (ret) { 01429 case IKS_NOMEM: 01430 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 01431 break; 01432 case IKS_BADXML: 01433 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 01434 break; 01435 case IKS_HOOK: 01436 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 01437 break; 01438 } 01439 if (ret != IKS_OK) { 01440 return ret; 01441 } 01442 ast_debug(3, "XML parsing successful\n"); 01443 } 01444 return IKS_OK; 01445 }
| static void * aji_recv_loop | ( | void * | data | ) | [static] |
Definition at line 2781 of file res_jabber.c.
References AJI_CONNECTED, AJI_DISCONNECTING, aji_reconnect(), aji_recv(), aji_send_raw(), ast_aji_client_destroy(), 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().
02782 { 02783 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02784 int res = IKS_HOOK; 02785 02786 while (res != IKS_OK) { 02787 ast_debug(3, "JABBER: Connecting.\n"); 02788 res = aji_reconnect(client); 02789 sleep(4); 02790 } 02791 02792 do { 02793 if (res == IKS_NET_RWERR || client->timeout == 0) { 02794 while (res != IKS_OK) { 02795 ast_debug(3, "JABBER: reconnecting.\n"); 02796 res = aji_reconnect(client); 02797 sleep(4); 02798 } 02799 } 02800 02801 res = aji_recv(client, 1); 02802 02803 if (client->state == AJI_DISCONNECTING) { 02804 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02805 pthread_exit(NULL); 02806 } 02807 02808 /* Decrease timeout if no data received, and delete 02809 * old messages globally */ 02810 if (res == IKS_NET_EXPIRED) { 02811 client->timeout--; 02812 delete_old_messages_all(client); 02813 } 02814 if (res == IKS_HOOK) { 02815 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02816 } else if (res == IKS_NET_TLSFAIL) { 02817 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02818 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02819 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02820 if (res == IKS_OK) { 02821 client->timeout = 50; 02822 } else { 02823 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02824 } 02825 } else if (res == IKS_NET_RWERR) { 02826 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02827 } 02828 } while (client); 02829 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02830 return 0; 02831 }
| static int aji_register_approve_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1833 of file res_jabber.c.
References ast_aji_client_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::jid, LOG_ERROR, and aji_client::mid.
Referenced by aji_create_client().
01834 { 01835 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01836 iks *iq = NULL, *presence = NULL, *x = NULL; 01837 01838 iq = iks_new("iq"); 01839 presence = iks_new("presence"); 01840 x = iks_new("x"); 01841 if (client && iq && presence && x) { 01842 if (!iks_find(pak->query, "remove")) { 01843 iks_insert_attrib(iq, "from", client->jid->full); 01844 iks_insert_attrib(iq, "to", pak->from->full); 01845 iks_insert_attrib(iq, "id", pak->id); 01846 iks_insert_attrib(iq, "type", "result"); 01847 ast_aji_send(client, iq); 01848 01849 iks_insert_attrib(presence, "from", client->jid->full); 01850 iks_insert_attrib(presence, "to", pak->from->partial); 01851 iks_insert_attrib(presence, "id", client->mid); 01852 ast_aji_increment_mid(client->mid); 01853 iks_insert_attrib(presence, "type", "subscribe"); 01854 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01855 iks_insert_node(presence, x); 01856 ast_aji_send(client, presence); 01857 } 01858 } else { 01859 ast_log(LOG_ERROR, "Out of memory.\n"); 01860 } 01861 01862 iks_delete(iq); 01863 iks_delete(presence); 01864 iks_delete(x); 01865 01866 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01867 return IKS_FILTER_EAT; 01868 }
| static int aji_register_query_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1876 of file res_jabber.c.
References ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, LOG_ERROR, and aji_client::user.
Referenced by aji_create_client().
01877 { 01878 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01879 struct aji_buddy *buddy = NULL; 01880 char *node = NULL; 01881 iks *iq = NULL, *query = NULL; 01882 01883 client = (struct aji_client *) data; 01884 01885 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01886 if (!buddy) { 01887 iks *error = NULL, *notacceptable = NULL; 01888 01889 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01890 iq = iks_new("iq"); 01891 query = iks_new("query"); 01892 error = iks_new("error"); 01893 notacceptable = iks_new("not-acceptable"); 01894 if (iq && query && error && notacceptable) { 01895 iks_insert_attrib(iq, "type", "error"); 01896 iks_insert_attrib(iq, "from", client->user); 01897 iks_insert_attrib(iq, "to", pak->from->full); 01898 iks_insert_attrib(iq, "id", pak->id); 01899 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01900 iks_insert_attrib(error, "code" , "406"); 01901 iks_insert_attrib(error, "type", "modify"); 01902 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01903 iks_insert_node(iq, query); 01904 iks_insert_node(iq, error); 01905 iks_insert_node(error, notacceptable); 01906 ast_aji_send(client, iq); 01907 } else { 01908 ast_log(LOG_ERROR, "Out of memory.\n"); 01909 } 01910 01911 iks_delete(error); 01912 iks_delete(notacceptable); 01913 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01914 iks *instructions = NULL; 01915 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01916 iq = iks_new("iq"); 01917 query = iks_new("query"); 01918 instructions = iks_new("instructions"); 01919 if (iq && query && instructions && client) { 01920 iks_insert_attrib(iq, "from", client->user); 01921 iks_insert_attrib(iq, "to", pak->from->full); 01922 iks_insert_attrib(iq, "id", pak->id); 01923 iks_insert_attrib(iq, "type", "result"); 01924 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01925 iks_insert_cdata(instructions, explain, 0); 01926 iks_insert_node(iq, query); 01927 iks_insert_node(query, instructions); 01928 ast_aji_send(client, iq); 01929 } else { 01930 ast_log(LOG_ERROR, "Out of memory.\n"); 01931 } 01932 01933 iks_delete(instructions); 01934 } 01935 iks_delete(iq); 01936 iks_delete(query); 01937 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 01938 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01939 return IKS_FILTER_EAT; 01940 }
| static int aji_reload | ( | int | reload | ) | [static] |
Definition at line 4739 of file res_jabber.c.
References AJI_CONNECTING, AJI_DISCONNECTED, aji_get_roster(), aji_init_event_distribution(), aji_load_config(), aji_recv_loop(), ast_aji_client_destroy(), 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().
04740 { 04741 int res; 04742 04743 ASTOBJ_CONTAINER_MARKALL(&clients); 04744 if (!(res = aji_load_config(reload))) { 04745 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 04746 return 0; 04747 } else if (res == -1) 04748 return 1; 04749 04750 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, ast_aji_client_destroy); 04751 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04752 ASTOBJ_RDLOCK(iterator); 04753 if (iterator->state == AJI_DISCONNECTED) { 04754 if (!iterator->thread) 04755 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 04756 } else if (iterator->state == AJI_CONNECTING) { 04757 aji_get_roster(iterator); 04758 if (iterator->distribute_events) { 04759 aji_init_event_distribution(iterator); 04760 } 04761 } 04762 04763 ASTOBJ_UNLOCK(iterator); 04764 }); 04765 04766 return 1; 04767 }
| static void aji_request_pubsub_nodes | ( | struct aji_client * | client, | |
| const char * | collection | |||
| ) | [static] |
Request item list from pubsub.
| client | the configured XMPP client we use to connect to a XMPP server | |
| collection | name of the collection for request |
Definition at line 3583 of file res_jabber.c.
References aji_build_node_request(), aji_receive_node_list(), ast_aji_send(), aji_client::f, and aji_client::mid.
Referenced by aji_cli_list_pubsub_nodes().
03584 { 03585 iks *request = aji_build_node_request(client, collection); 03586 03587 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE, 03588 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03589 IKS_RULE_DONE); 03590 ast_aji_send(client, request); 03591 iks_delete(request); 03592 03593 }
| static int aji_send_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 1118 of file res_jabber.c.
References args, ast_aji_client_destroy(), 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(), ASTOBJ_UNREF, and LOG_WARNING.
Referenced by load_module().
01119 { 01120 struct aji_client *client = NULL; 01121 char *s; 01122 AST_DECLARE_APP_ARGS(args, 01123 AST_APP_ARG(sender); 01124 AST_APP_ARG(recipient); 01125 AST_APP_ARG(message); 01126 ); 01127 01128 if (!data) { 01129 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01130 return -1; 01131 } 01132 s = ast_strdupa(data); 01133 01134 AST_STANDARD_APP_ARGS(args, s); 01135 if (args.argc < 3) { 01136 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01137 return -1; 01138 } 01139 01140 if (!(client = ast_aji_get_client(args.sender))) { 01141 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 01142 return -1; 01143 } 01144 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) { 01145 ast_aji_send_chat(client, args.recipient, args.message); 01146 } 01147 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01148 return 0; 01149 }
| static int aji_send_header | ( | struct aji_client * | client, | |
| const char * | to | |||
| ) | [static] |
Definition at line 1454 of file res_jabber.c.
References aji_send_raw(), len(), and aji_client::name_space.
Referenced by aji_act_hook().
01455 { 01456 char *msg; 01457 int len, err; 01458 01459 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 01460 msg = iks_malloc(len); 01461 if (!msg) 01462 return IKS_NOMEM; 01463 sprintf(msg, "<?xml version='1.0'?>" 01464 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 01465 "%s' to='%s' version='1.0'>", client->name_space, to); 01466 err = aji_send_raw(client, msg); 01467 iks_free(msg); 01468 if (err != IKS_OK) 01469 return err; 01470 01471 return IKS_OK; 01472 }
| static int aji_send_raw | ( | struct aji_client * | client, | |
| const char * | xmlstr | |||
| ) | [static] |
Definition at line 1494 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().
01495 { 01496 int ret; 01497 #ifdef HAVE_OPENSSL 01498 int len = strlen(xmlstr); 01499 01500 if (aji_is_secure(client)) { 01501 ret = SSL_write(client->ssl_session, xmlstr, len); 01502 if (ret) { 01503 /* Log the message here, because iksemel's logHook is 01504 unaccessible */ 01505 aji_log_hook(client, xmlstr, len, 0); 01506 return IKS_OK; 01507 } 01508 } 01509 #endif 01510 /* If needed, data will be sent unencrypted, and logHook will 01511 be called inside iks_send_raw */ 01512 ret = iks_send_raw(client->p, xmlstr); 01513 if (ret != IKS_OK) { 01514 return ret; 01515 } 01516 01517 return IKS_OK; 01518 }
| static int aji_send_raw_chat | ( | struct aji_client * | client, | |
| int | groupchat, | |||
| const char * | nick, | |||
| const char * | address, | |||
| const char * | message | |||
| ) | [static] |
sends messages.
| client | the configured XMPP client we use to connect to a XMPP server | |
| groupchat | ||
| nick | the nickname we use in chatrooms | |
| address | ||
| message |
Definition at line 2657 of file res_jabber.c.
References AJI_CONNECTED, AJI_MAX_JIDLEN, ast_aji_send(), ast_log(), aji_client::component, aji_client::jid, LOG_ERROR, LOG_WARNING, and aji_client::state.
Referenced by ast_aji_send_chat(), and ast_aji_send_groupchat().
02658 { 02659 int res = 0; 02660 iks *message_packet = NULL; 02661 char from[AJI_MAX_JIDLEN]; 02662 /* the nickname is used only in component mode */ 02663 if (nick && client->component) { 02664 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 02665 } else { 02666 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 02667 } 02668 02669 if (client->state != AJI_CONNECTED) { 02670 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02671 return -1; 02672 } 02673 02674 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message); 02675 if (!message_packet) { 02676 ast_log(LOG_ERROR, "Out of memory.\n"); 02677 return -1; 02678 } 02679 iks_insert_attrib(message_packet, "from", from); 02680 res = ast_aji_send(client, message_packet); 02681 iks_delete(message_packet); 02682 02683 return res; 02684 }
| static int aji_sendgroup_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Application to send a message to a groupchat.
| chan | ast_channel | |
| data | Data is sender|groupchat|message. |
| 0 | success | |
| -1 | error |
Definition at line 1191 of file res_jabber.c.
References AJI_MAX_RESJIDLEN, args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_send_groupchat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, aji_client::component, aji_client::jid, and LOG_ERROR.
Referenced by load_module().
01192 { 01193 struct aji_client *client = NULL; 01194 char *s; 01195 char nick[AJI_MAX_RESJIDLEN]; 01196 int res = 0; 01197 AST_DECLARE_APP_ARGS(args, 01198 AST_APP_ARG(sender); 01199 AST_APP_ARG(groupchat); 01200 AST_APP_ARG(message); 01201 AST_APP_ARG(nick); 01202 ); 01203 01204 if (!data) { 01205 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01206 return -1; 01207 } 01208 s = ast_strdupa(data); 01209 01210 AST_STANDARD_APP_ARGS(args, s); 01211 if (args.argc < 3 || args.argc > 4) { 01212 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01213 return -1; 01214 } 01215 01216 if (!(client = ast_aji_get_client(args.sender))) { 01217 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01218 return -1; 01219 } 01220 01221 if (ast_strlen_zero(args.nick) || args.argc == 3) { 01222 if (client->component) { 01223 sprintf(nick, "asterisk"); 01224 } else { 01225 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01226 } 01227 } else { 01228 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01229 } 01230 01231 if (strchr(args.groupchat, '@') && !ast_strlen_zero(args.message)) { 01232 res = ast_aji_send_groupchat(client, nick, args.groupchat, args.message); 01233 } 01234 01235 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01236 if (res != IKS_OK) { 01237 return -1; 01238 } 01239 return 0; 01240 }
| static int aji_set_group_presence | ( | struct aji_client * | client, | |
| char * | room, | |||
| int | level, | |||
| char * | nick, | |||
| char * | desc | |||
| ) | [static] |
Definition at line 4049 of file res_jabber.c.
References AJI_MAX_JIDLEN, ast_aji_send(), ast_log(), aji_client::component, aji_client::jid, LOG_ERROR, and MUC_NS.
Referenced by ast_aji_join_chat(), and ast_aji_leave_chat().
04050 { 04051 int res = 0; 04052 iks *presence = NULL, *x = NULL; 04053 char from[AJI_MAX_JIDLEN]; 04054 char roomid[AJI_MAX_JIDLEN]; 04055 04056 presence = iks_make_pres(level, NULL); 04057 x = iks_new("x"); 04058 04059 if (client->component) { 04060 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 04061 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick); 04062 } else { 04063 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 04064 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user); 04065 } 04066 04067 if (!presence || !x || !client) { 04068 ast_log(LOG_ERROR, "Out of memory.\n"); 04069 res = -1; 04070 goto safeout; 04071 } else { 04072 iks_insert_attrib(presence, "to", roomid); 04073 iks_insert_attrib(presence, "from", from); 04074 iks_insert_attrib(x, "xmlns", MUC_NS); 04075 iks_insert_node(presence, x); 04076 res = ast_aji_send(client, presence); 04077 } 04078 04079 safeout: 04080 iks_delete(presence); 04081 iks_delete(x); 04082 return res; 04083 }
| static void aji_set_presence | ( | struct aji_client * | client, | |
| char * | to, | |||
| char * | from, | |||
| int | level, | |||
| char * | desc | |||
| ) | [static] |
Definition at line 4007 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().
04008 { 04009 iks *presence = iks_make_pres(level, desc); 04010 iks *cnode = iks_new("c"); 04011 iks *priority = iks_new("priority"); 04012 char priorityS[10]; 04013 04014 if (presence && cnode && client && priority) { 04015 if (to) { 04016 iks_insert_attrib(presence, "to", to); 04017 } 04018 if (from) { 04019 iks_insert_attrib(presence, "from", from); 04020 } 04021 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 04022 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 04023 iks_insert_node(presence, priority); 04024 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 04025 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 04026 iks_insert_attrib(cnode, "ext", "voice-v1"); 04027 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 04028 iks_insert_node(presence, cnode); 04029 ast_aji_send(client, presence); 04030 } else { 04031 ast_log(LOG_ERROR, "Out of memory.\n"); 04032 } 04033 04034 iks_delete(cnode); 04035 iks_delete(presence); 04036 iks_delete(priority); 04037 }
| static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4201 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.
04202 { 04203 struct aji_resource *resource; 04204 struct aji_client *client; 04205 04206 switch (cmd) { 04207 case CLI_INIT: 04208 e->command = "jabber show buddies"; 04209 e->usage = 04210 "Usage: jabber show buddies\n" 04211 " Shows buddy lists of our clients\n"; 04212 return NULL; 04213 case CLI_GENERATE: 04214 return NULL; 04215 } 04216 04217 ast_cli(a->fd, "Jabber buddy lists\n"); 04218 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04219 ast_cli(a->fd, "Client: %s\n", iterator->user); 04220 client = iterator; 04221 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04222 ASTOBJ_RDLOCK(iterator); 04223 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name); 04224 if (!iterator->resources) 04225 ast_cli(a->fd, "\t\tResource: None\n"); 04226 for (resource = iterator->resources; resource; resource = resource->next) { 04227 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource); 04228 if (resource->cap) { 04229 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node); 04230 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version); 04231 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 04232 } 04233 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status); 04234 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority); 04235 } 04236 ASTOBJ_UNLOCK(iterator); 04237 }); 04238 iterator = client; 04239 }); 04240 return CLI_SUCCESS; 04241 }
| static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4155 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.
04156 { 04157 char *status; 04158 int count = 0; 04159 04160 switch (cmd) { 04161 case CLI_INIT: 04162 e->command = "jabber show connections"; 04163 e->usage = 04164 "Usage: jabber show connections\n" 04165 " Shows state of client and component connections\n"; 04166 return NULL; 04167 case CLI_GENERATE: 04168 return NULL; 04169 } 04170 04171 ast_cli(a->fd, "Jabber Users and their status:\n"); 04172 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04173 ASTOBJ_RDLOCK(iterator); 04174 count++; 04175 switch (iterator->state) { 04176 case AJI_DISCONNECTED: 04177 status = "Disconnected"; 04178 break; 04179 case AJI_CONNECTING: 04180 status = "Connecting"; 04181 break; 04182 case AJI_CONNECTED: 04183 status = "Connected"; 04184 break; 04185 default: 04186 status = "Unknown"; 04187 } 04188 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status); 04189 ASTOBJ_UNLOCK(iterator); 04190 }); 04191 ast_cli(a->fd, "----\n"); 04192 ast_cli(a->fd, " Number of users: %d\n", count); 04193 return CLI_SUCCESS; 04194 }
| static int aji_start_sasl | ( | struct aji_client * | client, | |
| enum ikssasltype | type, | |||
| char * | username, | |||
| char * | pass | |||
| ) | [static] |
Definition at line 1563 of file res_jabber.c.
References aji_is_secure(), ast_aji_send(), ast_base64encode(), ast_log(), base64, len(), LOG_ERROR, and aji_client::p.
Referenced by aji_act_hook().
01564 { 01565 iks *x = NULL; 01566 int len; 01567 char *s; 01568 char *base64; 01569 01570 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 01571 iks_start_sasl is an iksemel API function and relies on GnuTLS, 01572 whereas we use OpenSSL */ 01573 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 01574 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 01575 if (!(type & IKS_STREAM_SASL_PLAIN)) { 01576 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 01577 return IKS_NET_NOTSUPP; 01578 } 01579 01580 x = iks_new("auth"); 01581 if (!x) { 01582 ast_log(LOG_ERROR, "Out of memory.\n"); 01583 return IKS_NET_NOTSUPP; 01584 } 01585 01586 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 01587 len = strlen(username) + strlen(pass) + 3; 01588 s = alloca(len); 01589 base64 = alloca((len + 2) * 4 / 3); 01590 iks_insert_attrib(x, "mechanism", "PLAIN"); 01591 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 01592 01593 /* exclude the NULL training byte from the base64 encoding operation 01594 as some XMPP servers will refuse it. 01595 The format for authentication is [authzid]\0authcid\0password 01596 not [authzid]\0authcid\0password\0 */ 01597 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 01598 iks_insert_cdata(x, base64, 0); 01599 ast_aji_send(client, x); 01600 iks_delete(x); 01601 01602 return IKS_OK; 01603 }
| static int aji_status_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 630 of file res_jabber.c.
References aji_find_resource(), args, ast_aji_buddy_destroy(), ast_aji_client_destroy(), 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, ASTOBJ_UNREF, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), aji_resource::resource, aji_buddy::resources, aji_resource::status, and status.
Referenced by load_module().
00631 { 00632 struct aji_client *client = NULL; 00633 struct aji_buddy *buddy = NULL; 00634 struct aji_resource *r = NULL; 00635 char *s = NULL; 00636 int stat = 7; 00637 char status[2]; 00638 static int deprecation_warning = 0; 00639 AST_DECLARE_APP_ARGS(args, 00640 AST_APP_ARG(sender); 00641 AST_APP_ARG(jid); 00642 AST_APP_ARG(variable); 00643 ); 00644 AST_DECLARE_APP_ARGS(jid, 00645 AST_APP_ARG(screenname); 00646 AST_APP_ARG(resource); 00647 ); 00648 00649 if (deprecation_warning++ % 10 == 0) { 00650 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00651 } 00652 00653 if (!data) { 00654 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00655 return 0; 00656 } 00657 s = ast_strdupa(data); 00658 AST_STANDARD_APP_ARGS(args, s); 00659 00660 if (args.argc != 3) { 00661 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00662 return -1; 00663 } 00664 00665 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00666 if (jid.argc < 1 || jid.argc > 2) { 00667 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00668 return -1; 00669 } 00670 00671 if (!(client = ast_aji_get_client(args.sender))) { 00672 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00673 return -1; 00674 } 00675 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00676 if (!buddy) { 00677 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00678 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00679 return -1; 00680 } 00681 r = aji_find_resource(buddy, jid.resource); 00682 if (!r && buddy->resources) { 00683 r = buddy->resources; 00684 } 00685 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00686 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00687 if (!r) { 00688 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00689 } else { 00690 stat = r->status; 00691 } 00692 snprintf(status, sizeof(status), "%d", stat); 00693 pbx_builtin_setvar_helper(chan, args.variable, status); 00694 return 0; 00695 }
| static char * aji_test | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4248 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.
04249 { 04250 struct aji_client *client; 04251 struct aji_resource *resource; 04252 const char *name; 04253 struct aji_message *tmp; 04254 04255 switch (cmd) { 04256 case CLI_INIT: 04257 e->command = "jabber test"; 04258 e->usage = 04259 "Usage: jabber test <connection>\n" 04260 " Sends test message for debugging purposes. A specific client\n" 04261 " as configured in jabber.conf must be specified.\n"; 04262 return NULL; 04263 case CLI_GENERATE: 04264 return NULL; 04265 } 04266 04267 if (a->argc != 3) { 04268 return CLI_SHOWUSAGE; 04269 } 04270 name = a->argv[2]; 04271 04272 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 04273 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 04274 return CLI_FAILURE; 04275 } 04276 04277 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 04278 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 04279 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04280 ASTOBJ_RDLOCK(iterator); 04281 ast_verbose("User: %s\n", iterator->name); 04282 for (resource = iterator->resources; resource; resource = resource->next) { 04283 ast_verbose("Resource: %s\n", resource->resource); 04284 if (resource->cap) { 04285 ast_verbose(" client: %s\n", resource->cap->parent->node); 04286 ast_verbose(" version: %s\n", resource->cap->version); 04287 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 04288 } 04289 ast_verbose(" Priority: %d\n", resource->priority); 04290 ast_verbose(" Status: %d\n", resource->status); 04291 ast_verbose(" Message: %s\n", S_OR(resource->description, "")); 04292 } 04293 ASTOBJ_UNLOCK(iterator); 04294 }); 04295 ast_verbose("\nOooh a working message stack!\n"); 04296 AST_LIST_LOCK(&client->messages); 04297 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 04298 //ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 04299 } 04300 AST_LIST_UNLOCK(&client->messages); 04301 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04302 04303 return CLI_SUCCESS; 04304 }
| void ast_aji_buddy_destroy | ( | struct aji_buddy * | obj | ) |
Destructor function for buddies to be used with ASTOBJ_UNREF
Definition at line 442 of file res_jabber.c.
References ast_free, aji_resource::description, aji_resource::next, and aji_buddy::resources.
Referenced by acf_jabberstatus_read(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), aji_handle_presence(), aji_handle_subscribe(), aji_register_query_handler(), aji_status_exec(), ast_aji_client_destroy(), gtalk_alloc(), gtalk_member_destroy(), jingle_alloc(), and jingle_member_destroy().
00443 { 00444 struct aji_resource *tmp; 00445 00446 while ((tmp = obj->resources)) { 00447 obj->resources = obj->resources->next; 00448 ast_free(tmp->description); 00449 ast_free(tmp); 00450 } 00451 00452 ast_free(obj); 00453 }
| void ast_aji_client_destroy | ( | struct aji_client * | obj | ) |
Destructor function for clients to be used with ASTOBJ_UNREF after calls to ast_aji_get_client
Definition at line 420 of file res_jabber.c.
References aji_message_destroy(), ast_aji_buddy_destroy(), ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, aji_client::buddies, aji_client::f, aji_message::list, aji_client::messages, aji_client::p, and aji_client::stack.
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_act_hook(), aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_client_connect(), aji_client_info_handler(), aji_create_client(), aji_devstate_cb(), aji_dinfo_handler(), aji_ditems_handler(), aji_handle_pubsub_error(), aji_join_exec(), aji_leave_exec(), aji_log_hook(), aji_mwi_cb(), aji_receive_node_list(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), ast_aji_disconnect(), gtalk_load_config(), gtalk_member_destroy(), gtalk_newcall(), gtalk_request(), jingle_load_config(), jingle_member_destroy(), jingle_newcall(), jingle_request(), manager_jabber_send(), msg_send_cb(), and unload_module().
00421 { 00422 struct aji_message *tmp; 00423 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, ast_aji_buddy_destroy); 00424 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00425 iks_filter_delete(obj->f); 00426 iks_parser_delete(obj->p); 00427 iks_stack_delete(obj->stack); 00428 AST_LIST_LOCK(&obj->messages); 00429 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00430 aji_message_destroy(tmp); 00431 } 00432 AST_LIST_HEAD_DESTROY(&obj->messages); 00433 ast_free(obj); 00434 }
| 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 2694 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02695 { 02696 int res = 0; 02697 iks *iq = NULL; 02698 iq = iks_new("iq"); 02699 02700 if (iq && client) { 02701 iks_insert_attrib(iq, "type", "get"); 02702 iks_insert_attrib(iq, "to", server); 02703 iks_insert_attrib(iq, "id", client->mid); 02704 ast_aji_increment_mid(client->mid); 02705 ast_aji_send(client, iq); 02706 } else { 02707 ast_log(LOG_ERROR, "Out of memory.\n"); 02708 } 02709 02710 iks_delete(iq); 02711 02712 return res; 02713 }
| 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 3201 of file res_jabber.c.
References ast_aji_client_destroy(), ast_verb, ASTOBJ_UNREF, and aji_client::p.
Referenced by unload_module().
03202 { 03203 if (client) { 03204 ast_verb(4, "JABBER: Disconnecting\n"); 03205 #ifdef HAVE_OPENSSL 03206 if (client->stream_flags & SECURE) { 03207 SSL_shutdown(client->ssl_session); 03208 SSL_CTX_free(client->ssl_context); 03209 SSL_free(client->ssl_session); 03210 } 03211 #endif 03212 iks_disconnect(client->p); 03213 iks_parser_delete(client->p); 03214 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03215 } 03216 03217 return 1; 03218 }
| struct aji_client* ast_aji_get_client | ( | const char * | name | ) | [read] |
grab a aji_client structure by label name or JID. Bumps the refcount. (without the resource string)
| name | label or JID |
Definition at line 4660 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, clients, and strsep().
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_join_exec(), aji_leave_exec(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), gtalk_create_member(), gtalk_newcall(), gtalk_request(), jingle_create_member(), jingle_newcall(), jingle_request(), manager_jabber_send(), and msg_send_cb().
04661 { 04662 struct aji_client *client = NULL; 04663 char *aux = NULL; 04664 04665 client = ASTOBJ_CONTAINER_FIND(&clients, name); 04666 if (!client && strchr(name, '@')) { 04667 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04668 aux = ast_strdupa(iterator->user); 04669 if (strchr(aux, '/')) { 04670 /* strip resource for comparison */ 04671 aux = strsep(&aux, "/"); 04672 } 04673 if (!strncasecmp(aux, name, strlen(aux))) { 04674 client = ASTOBJ_REF(iterator); 04675 } 04676 }); 04677 } 04678 04679 return client; 04680 }
| struct aji_client_container* ast_aji_get_clients | ( | void | ) | [read] |
Definition at line 4682 of file res_jabber.c.
References clients.
Referenced by gtalk_load_config(), and jingle_load_config().
04683 { 04684 return &clients; 04685 }
| void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
| mid | char. |
Definition at line 2838 of file res_jabber.c.
Referenced by aji_act_hook(), aji_handle_presence(), aji_pubsub_iq_create(), aji_register_approve_handler(), ast_aji_create_chat(), ast_aji_invite_chat(), gtalk_action(), gtalk_create_candidates(), gtalk_invite(), jingle_accept_call(), jingle_action(), jingle_create_candidates(), jingle_digit(), and jingle_transmit_invite().
02839 { 02840 int i = 0; 02841 02842 for (i = strlen(mid) - 1; i >= 0; i--) { 02843 if (mid[i] != 'z') { 02844 mid[i] = mid[i] + 1; 02845 i = 0; 02846 } else 02847 mid[i] = 'a'; 02848 } 02849 }
| int ast_aji_invite_chat | ( | struct aji_client * | client, | |
| char * | user, | |||
| char * | room, | |||
| char * | message | |||
| ) |
invite to a chatroom.
Definition at line 2746 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02747 { 02748 int res = 0; 02749 iks *invite, *body, *namespace; 02750 02751 invite = iks_new("message"); 02752 body = iks_new("body"); 02753 namespace = iks_new("x"); 02754 if (client && invite && body && namespace) { 02755 iks_insert_attrib(invite, "to", user); 02756 iks_insert_attrib(invite, "id", client->mid); 02757 ast_aji_increment_mid(client->mid); 02758 iks_insert_cdata(body, message, 0); 02759 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02760 iks_insert_attrib(namespace, "jid", room); 02761 iks_insert_node(invite, body); 02762 iks_insert_node(invite, namespace); 02763 res = ast_aji_send(client, invite); 02764 } else { 02765 ast_log(LOG_ERROR, "Out of memory.\n"); 02766 } 02767 02768 iks_delete(body); 02769 iks_delete(namespace); 02770 iks_delete(invite); 02771 02772 return res; 02773 }
| int ast_aji_join_chat | ( | struct aji_client * | client, | |
| char * | room, | |||
| char * | nick | |||
| ) |
join a chatroom.
| client | the configured XMPP client we use to connect to a XMPP server | |
| room | room to join | |
| nick | the nickname to use in this room |
Definition at line 2722 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_join_exec().
02723 { 02724 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL); 02725 }
| int ast_aji_leave_chat | ( | struct aji_client * | client, | |
| char * | room, | |||
| char * | nick | |||
| ) |
leave a chatroom.
| client | the configured XMPP client we use to connect to a XMPP server | |
| room | room to leave | |
| nick | the nickname used in this room |
Definition at line 2734 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_leave_exec().
02735 { 02736 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL); 02737 }
| 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 1480 of file res_jabber.c.
References aji_send_raw().
Referenced by aji_act_hook(), aji_client_info_handler(), aji_create_pubsub_node(), aji_delete_pubsub_node(), aji_dinfo_handler(), aji_ditems_handler(), aji_get_roster(), aji_handle_presence(), aji_handle_pubsub_error(), aji_handle_subscribe(), aji_pruneregister(), aji_publish_device_state(), aji_publish_mwi(), aji_pubsub_purge_nodes(), aji_pubsub_subscribe(), aji_register_approve_handler(), aji_register_query_handler(), aji_request_pubsub_nodes(), aji_send_raw_chat(), aji_set_group_presence(), aji_set_presence(), aji_start_sasl(), ast_aji_create_chat(), ast_aji_invite_chat(), gtalk_action(), gtalk_add_candidate(), gtalk_create_candidates(), gtalk_invite(), gtalk_response(), jingle_accept_call(), jingle_action(), jingle_add_candidate(), jingle_create_candidates(), jingle_digit(), jingle_response(), and jingle_transmit_invite().
01481 { 01482 return aji_send_raw(client, iks_string(iks_stack(x), x)); 01483 }
| 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 2630 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_send_exec(), aji_test(), gtalk_sendtext(), jingle_sendtext(), manager_jabber_send(), and msg_send_cb().
02631 { 02632 return aji_send_raw_chat(client, 0, NULL, address, message); 02633 }
| int ast_aji_send_groupchat | ( | struct aji_client * | client, | |
| const char * | nick, | |||
| const char * | address, | |||
| const char * | message | |||
| ) |
sends message to a groupchat Prior to sending messages to a groupchat, one must be connected to it.
| client | the configured XMPP client we use to connect to a XMPP server | |
| nick | the nickname we use in the chatroom | |
| address | the user the messages must be sent to | |
| message | the message to send |
Definition at line 2644 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_sendgroup_exec().
02644 { 02645 return aji_send_raw_chat(client, 1, nick, address, message); 02646 }
| static int delete_old_messages | ( | struct aji_client * | client, | |
| char * | from | |||
| ) | [static] |
Definition at line 940 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().
00941 { 00942 int deleted = 0; 00943 int isold = 0; 00944 struct aji_message *tmp = NULL; 00945 if (!client) { 00946 ast_log(LOG_ERROR, "Cannot find our XMPP client\n"); 00947 return -1; 00948 } 00949 00950 /* remove old messages */ 00951 AST_LIST_LOCK(&client->messages); 00952 if (AST_LIST_EMPTY(&client->messages)) { 00953 AST_LIST_UNLOCK(&client->messages); 00954 return 0; 00955 } 00956 00957 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00958 if (isold) { 00959 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00960 AST_LIST_REMOVE_CURRENT(list); 00961 aji_message_destroy(tmp); 00962 deleted ++; 00963 } 00964 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00965 isold = 1; 00966 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00967 AST_LIST_REMOVE_CURRENT(list); 00968 aji_message_destroy(tmp); 00969 deleted ++; 00970 } 00971 } 00972 } 00973 AST_LIST_TRAVERSE_SAFE_END; 00974 AST_LIST_UNLOCK(&client->messages); 00975 00976 return deleted; 00977 }
| static int delete_old_messages_all | ( | struct aji_client * | client | ) | [static] |
Definition at line 987 of file res_jabber.c.
References delete_old_messages().
Referenced by aji_recv_loop().
00988 { 00989 return delete_old_messages(client, NULL); 00990 }
| static int gtalk_yuck | ( | iks * | node | ) | [static] |
Definition at line 576 of file res_jabber.c.
References ast_debug.
Referenced by aji_handle_presence().
00577 { 00578 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) { 00579 ast_debug(1, "Found resource with Googletalk voice capabilities\n"); 00580 return 1; 00581 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) { 00582 ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n"); 00583 return 1; 00584 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) { 00585 ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n"); 00586 return 1; 00587 } 00588 00589 return 0; 00590 }
| static iks * jabber_make_auth | ( | iksid * | id, | |
| const char * | pass, | |||
| const char * | sid | |||
| ) | [static] |
Definition at line 600 of file res_jabber.c.
References ast_sha1_hash().
Referenced by aji_act_hook().
00601 { 00602 iks *x, *y; 00603 x = iks_new("iq"); 00604 iks_insert_attrib(x, "type", "set"); 00605 y = iks_insert(x, "query"); 00606 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00607 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00608 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00609 if (sid) { 00610 char buf[41]; 00611 char sidpass[100]; 00612 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00613 ast_sha1_hash(buf, sidpass); 00614 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00615 } else { 00616 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00617 } 00618 return x; 00619 }
| static int load_module | ( | void | ) | [static] |
Definition at line 4814 of file res_jabber.c.
References aji_join_exec(), aji_leave_exec(), aji_reload(), aji_send_exec(), aji_sendgroup_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_msg_tech_register(), ast_mutex_init, ast_register_application_xml, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, and manager_jabber_send().
04815 { 04816 ASTOBJ_CONTAINER_INIT(&clients); 04817 if (!aji_reload(0)) 04818 return AST_MODULE_LOAD_DECLINE; 04819 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 04820 ast_register_application_xml(app_ajisend, aji_send_exec); 04821 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec); 04822 ast_register_application_xml(app_ajistatus, aji_status_exec); 04823 ast_register_application_xml(app_ajijoin, aji_join_exec); 04824 ast_register_application_xml(app_ajileave, aji_leave_exec); 04825 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04826 ast_custom_function_register(&jabberstatus_function); 04827 ast_custom_function_register(&jabberreceive_function); 04828 ast_msg_tech_register(&msg_tech); 04829 04830 ast_mutex_init(&messagelock); 04831 ast_cond_init(&message_received_condition, NULL); 04832 return 0; 04833 }
| static int manager_jabber_send | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4694 of file res_jabber.c.
References ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_send_chat(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), and ASTOBJ_UNREF.
Referenced by load_module().
04695 { 04696 struct aji_client *client = NULL; 04697 const char *id = astman_get_header(m, "ActionID"); 04698 const char *jabber = astman_get_header(m, "Jabber"); 04699 const char *screenname = astman_get_header(m, "ScreenName"); 04700 const char *message = astman_get_header(m, "Message"); 04701 04702 if (ast_strlen_zero(jabber)) { 04703 astman_send_error(s, m, "No transport specified"); 04704 return 0; 04705 } 04706 if (ast_strlen_zero(screenname)) { 04707 astman_send_error(s, m, "No ScreenName specified"); 04708 return 0; 04709 } 04710 if (ast_strlen_zero(message)) { 04711 astman_send_error(s, m, "No Message specified"); 04712 return 0; 04713 } 04714 04715 astman_send_ack(s, m, "Attempting to send Jabber Message"); 04716 client = ast_aji_get_client(jabber); 04717 if (!client) { 04718 astman_send_error(s, m, "Could not find Sender"); 04719 return 0; 04720 } 04721 if (strchr(screenname, '@') && message) { 04722 ast_aji_send_chat(client, screenname, message); 04723 astman_append(s, "Response: Success\r\n"); 04724 } else { 04725 astman_append(s, "Response: Error\r\n"); 04726 } 04727 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04728 if (!ast_strlen_zero(id)) { 04729 astman_append(s, "ActionID: %s\r\n", id); 04730 } 04731 astman_append(s, "\r\n"); 04732 return 0; 04733 }
| static int msg_send_cb | ( | const struct ast_msg * | msg, | |
| const char * | to, | |||
| const char * | from | |||
| ) | [static] |
Definition at line 1151 of file res_jabber.c.
References ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_send_chat(), ast_debug, ast_log(), ast_msg_get_body(), ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, LOG_ERROR, LOG_WARNING, aji_client::name, and strsep().
01152 { 01153 struct aji_client *client; 01154 char *sender; 01155 char *dest; 01156 int res; 01157 01158 sender = ast_strdupa(from); 01159 strsep(&sender, ":"); 01160 dest = ast_strdupa(to); 01161 strsep(&dest, ":"); 01162 01163 if (ast_strlen_zero(sender)) { 01164 ast_log(LOG_ERROR, "MESSAGE(from) of '%s' invalid for xmpp\n", from); 01165 return -1; 01166 } 01167 01168 if (!(client = ast_aji_get_client(sender))) { 01169 ast_log(LOG_WARNING, "Could not finder account to send from as '%s'\n", sender); 01170 return -1; 01171 } 01172 01173 ast_debug(1, "Sending message to '%s' from '%s'\n", dest, client->name); 01174 01175 res = ast_aji_send_chat(client, dest, ast_msg_get_body(msg)); 01176 if (res != IKS_OK) { 01177 ast_log(LOG_WARNING, "Failed to send xmpp message (%d).\n", res); 01178 } 01179 01180 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01181 return res == IKS_OK ? 0 : -1; 01182 }
| static int reload | ( | void | ) | [static] |
Definition at line 4839 of file res_jabber.c.
References aji_reload().
04840 { 04841 aji_reload(1); 04842 return 0; 04843 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 4773 of file res_jabber.c.
References AJI_DISCONNECTING, ARRAY_LEN, ast_aji_client_destroy(), ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_custom_function_unregister(), ast_debug, ast_event_unsubscribe(), ast_manager_unregister(), ast_msg_tech_unregister(), ast_mutex_destroy, ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, and clients.
04774 { 04775 ast_msg_tech_unregister(&msg_tech); 04776 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04777 ast_unregister_application(app_ajisend); 04778 ast_unregister_application(app_ajisendgroup); 04779 ast_unregister_application(app_ajistatus); 04780 ast_unregister_application(app_ajijoin); 04781 ast_unregister_application(app_ajileave); 04782 ast_manager_unregister("JabberSend"); 04783 ast_custom_function_unregister(&jabberstatus_function); 04784 if (mwi_sub) { 04785 ast_event_unsubscribe(mwi_sub); 04786 } 04787 if (device_state_sub) { 04788 ast_event_unsubscribe(device_state_sub); 04789 } 04790 ast_custom_function_unregister(&jabberreceive_function); 04791 04792 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04793 ASTOBJ_WRLOCK(iterator); 04794 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 04795 iterator->state = AJI_DISCONNECTING; 04796 ASTOBJ_UNLOCK(iterator); 04797 pthread_join(iterator->thread, NULL); 04798 ast_aji_disconnect(iterator); 04799 }); 04800 04801 ASTOBJ_CONTAINER_DESTROYALL(&clients, ast_aji_client_destroy); 04802 ASTOBJ_CONTAINER_DESTROY(&clients); 04803 04804 ast_cond_destroy(&message_received_condition); 04805 ast_mutex_destroy(&messagelock); 04806 04807 return 0; 04808 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .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, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 4850 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
Definition at line 383 of file res_jabber.c.
char* app_ajijoin = "JabberJoin" [static] |
Definition at line 399 of file res_jabber.c.
char* app_ajileave = "JabberLeave" [static] |
Definition at line 400 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 396 of file res_jabber.c.
char* app_ajisendgroup = "JabberSendGroup" [static] |
Definition at line 397 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 398 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4850 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL [static] |
Definition at line 403 of file res_jabber.c.
struct aji_client_container clients [static] |
Definition at line 402 of file res_jabber.c.
Referenced by aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), 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_event_sub* device_state_sub = NULL [static] |
Definition at line 405 of file res_jabber.c.
struct ast_flags globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } [static] |
struct ast_custom_function jabberreceive_function [static] |
Initial value:
{
.name = "JABBER_RECEIVE",
.read = acf_jabberreceive_read,
}
Definition at line 926 of file res_jabber.c.
struct ast_custom_function jabberstatus_function [static] |
Initial value:
{
.name = "JABBER_STATUS",
.read = acf_jabberstatus_read,
}
Definition at line 763 of file res_jabber.c.
ast_cond_t message_received_condition [static] |
Definition at line 406 of file res_jabber.c.
ast_mutex_t messagelock [static] |
Definition at line 407 of file res_jabber.c.
struct ast_msg_tech msg_tech [static] |
Initial value:
{
.name = "xmpp",
.msg_send = msg_send_cb,
}
Definition at line 378 of file res_jabber.c.
struct ast_event_sub* mwi_sub = NULL [static] |
Definition at line 404 of file res_jabber.c.
struct ast_flags pubsubflags = { 0 } [static] |
1.5.6