A resource for interfacing Asterisk directly as a client or a component to a XMPP/Jabber compliant server. More...
#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"
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, unsigned int cachable) |
| 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, unsigned int cachable) |
| 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_start_tls (struct aji_client *client) |
| static int | aji_status_exec (struct ast_channel *chan, const char *data) |
| static int | aji_tls_handshake (struct aji_client *client) |
| 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 | 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 = "95089850e3c922fa176f9bd274fd8109" , .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_event_sub * | mwi_sub = NULL |
| static struct ast_flags | pubsubflags = { 0 } |
| PubSub flags, initialized to default values. | |
A resource for interfacing Asterisk directly as a client or a component to a XMPP/Jabber compliant server.
References:
If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?
Dialplan applications need RETURN variable, like JABBERSENDSTATUS
Definition in file res_jabber.c.
| #define JABBER_CONFIG "jabber.conf" |
Definition at line 285 of file res_jabber.c.
Referenced by aji_load_config().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 4761 of file res_jabber.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 4761 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 767 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_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, and parse().
00768 { 00769 char *parse = NULL; 00770 int timeout; 00771 int jidlen, resourcelen; 00772 struct timeval start; 00773 long diff = 0; 00774 struct aji_client *client = NULL; 00775 int found = 0; 00776 struct aji_message *tmp = NULL; 00777 AST_DECLARE_APP_ARGS(args, 00778 AST_APP_ARG(account); 00779 AST_APP_ARG(jid); 00780 AST_APP_ARG(timeout); 00781 ); 00782 AST_DECLARE_APP_ARGS(jid, 00783 AST_APP_ARG(screenname); 00784 AST_APP_ARG(resource); 00785 ); 00786 00787 if (ast_strlen_zero(data)) { 00788 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00789 return -1; 00790 } 00791 00792 parse = ast_strdupa(data); 00793 AST_STANDARD_APP_ARGS(args, parse); 00794 00795 if (args.argc < 2 || args.argc > 3) { 00796 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00797 return -1; 00798 } 00799 00800 parse = ast_strdupa(args.jid); 00801 AST_NONSTANDARD_APP_ARGS(jid, parse, '/'); 00802 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) { 00803 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse); 00804 return -1; 00805 } 00806 00807 if (ast_strlen_zero(args.timeout)) { 00808 timeout = 20; 00809 } else { 00810 sscanf(args.timeout, "%d", &timeout); 00811 if (timeout <= 0) { 00812 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 00813 return -1; 00814 } 00815 } 00816 00817 jidlen = strlen(jid.screenname); 00818 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource); 00819 00820 client = ast_aji_get_client(args.account); 00821 if (!client) { 00822 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account); 00823 return -1; 00824 } 00825 00826 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid); 00827 00828 start = ast_tvnow(); 00829 00830 if (ast_autoservice_start(chan) < 0) { 00831 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", chan->name); 00832 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00833 return -1; 00834 } 00835 00836 /* search the messages list, grab the first message that matches with 00837 * the from JID we're expecting, and remove it from the messages list */ 00838 while (diff < timeout) { 00839 struct timespec ts = { 0, }; 00840 struct timeval wait; 00841 int res; 00842 00843 wait = ast_tvadd(start, ast_tv(timeout, 0)); 00844 ts.tv_sec = wait.tv_sec; 00845 ts.tv_nsec = wait.tv_usec * 1000; 00846 00847 /* wait up to timeout seconds for an incoming message */ 00848 ast_mutex_lock(&messagelock); 00849 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts); 00850 ast_mutex_unlock(&messagelock); 00851 if (res == ETIMEDOUT) { 00852 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout); 00853 break; 00854 } 00855 00856 AST_LIST_LOCK(&client->messages); 00857 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00858 if (jid.argc == 1) { 00859 /* no resource provided, compare bare JIDs */ 00860 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00861 continue; 00862 } 00863 } else { 00864 /* resource appended, compare bare JIDs and resources */ 00865 char *resource = strchr(tmp->from, '/'); 00866 if (!resource || strlen(resource) == 0) { 00867 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from); 00868 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00869 continue; 00870 } 00871 } else { 00872 resource ++; 00873 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) { 00874 continue; 00875 } 00876 } 00877 } 00878 /* check if the message is not too old */ 00879 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00880 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from); 00881 AST_LIST_REMOVE_CURRENT(list); 00882 aji_message_destroy(tmp); 00883 continue; 00884 } 00885 found = 1; 00886 ast_copy_string(buf, tmp->message, buflen); 00887 AST_LIST_REMOVE_CURRENT(list); 00888 aji_message_destroy(tmp); 00889 break; 00890 } 00891 AST_LIST_TRAVERSE_SAFE_END; 00892 AST_LIST_UNLOCK(&client->messages); 00893 if (found) { 00894 break; 00895 } 00896 00897 /* check timeout */ 00898 diff = ast_tvdiff_ms(ast_tvnow(), start); 00899 } 00900 00901 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00902 if (ast_autoservice_stop(chan) < 0) { 00903 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", chan->name); 00904 } 00905 00906 /* return if we timed out */ 00907 if (!found) { 00908 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); 00909 return -1; 00910 } 00911 00912 return 0; 00913 }
| static int acf_jabberstatus_read | ( | struct ast_channel * | chan, | |
| const char * | name, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 696 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.
00697 { 00698 struct aji_client *client = NULL; 00699 struct aji_buddy *buddy = NULL; 00700 struct aji_resource *r = NULL; 00701 int stat = 7; 00702 AST_DECLARE_APP_ARGS(args, 00703 AST_APP_ARG(sender); 00704 AST_APP_ARG(jid); 00705 ); 00706 AST_DECLARE_APP_ARGS(jid, 00707 AST_APP_ARG(screenname); 00708 AST_APP_ARG(resource); 00709 ); 00710 00711 if (!data) { 00712 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00713 return 0; 00714 } 00715 AST_STANDARD_APP_ARGS(args, data); 00716 00717 if (args.argc != 2) { 00718 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00719 return -1; 00720 } 00721 00722 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00723 if (jid.argc < 1 || jid.argc > 2) { 00724 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00725 return -1; 00726 } 00727 00728 if (!(client = ast_aji_get_client(args.sender))) { 00729 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00730 return -1; 00731 } 00732 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00733 if (!buddy) { 00734 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00735 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00736 return -1; 00737 } 00738 r = aji_find_resource(buddy, jid.resource); 00739 if (!r && buddy->resources) { 00740 r = buddy->resources; 00741 } 00742 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00743 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00744 if (!r) { 00745 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00746 } else { 00747 stat = r->status; 00748 } 00749 snprintf(buf, buflen, "%d", stat); 00750 return 0; 00751 }
| static int aji_act_hook | ( | void * | data, | |
| int | type, | |||
| iks * | node | |||
| ) | [static] |
Definition at line 1569 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(), aji_start_tls(), aji_tls_handshake(), ast_aji_client_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_asprintf, 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::stream_flags, TRY_SECURE, aji_client::usesasl, and aji_client::usetls.
Referenced by aji_create_client().
01570 { 01571 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01572 ikspak *pak = NULL; 01573 iks *auth = NULL; 01574 int features = 0; 01575 01576 if (!node) { 01577 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 01578 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01579 return IKS_HOOK; 01580 } 01581 01582 if (client->state == AJI_DISCONNECTING) { 01583 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01584 return IKS_HOOK; 01585 } 01586 01587 pak = iks_packet(node); 01588 01589 /* work around iksemel's impossibility to recognize node names 01590 * containing a semicolon. Set the namespace of the corresponding 01591 * node accordingly. */ 01592 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) { 01593 char *node_ns = NULL; 01594 char attr[AJI_MAX_ATTRLEN]; 01595 char *node_name = iks_name(iks_child(node)); 01596 char *aux = strchr(node_name, ':') + 1; 01597 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name); 01598 node_ns = iks_find_attrib(iks_child(node), attr); 01599 if (node_ns) { 01600 pak->ns = node_ns; 01601 pak->query = iks_child(node); 01602 } 01603 } 01604 01605 01606 if (!client->component) { /*client */ 01607 switch (type) { 01608 case IKS_NODE_START: 01609 if (client->usetls && !aji_is_secure(client)) { 01610 #ifndef HAVE_OPENSSL 01611 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"); 01612 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01613 return IKS_HOOK; 01614 #else 01615 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 01616 ast_log(LOG_ERROR, "Could not start TLS\n"); 01617 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01618 return IKS_HOOK; 01619 } 01620 #endif 01621 break; 01622 } 01623 if (!client->usesasl) { 01624 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); 01625 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 01626 if (auth) { 01627 iks_insert_attrib(auth, "id", client->mid); 01628 iks_insert_attrib(auth, "to", client->jid->server); 01629 ast_aji_increment_mid(client->mid); 01630 ast_aji_send(client, auth); 01631 iks_delete(auth); 01632 } else { 01633 ast_log(LOG_ERROR, "Out of memory.\n"); 01634 } 01635 } 01636 break; 01637 01638 case IKS_NODE_NORMAL: 01639 #ifdef HAVE_OPENSSL 01640 if (client->stream_flags & TRY_SECURE) { 01641 if (!strcmp("proceed", iks_name(node))) { 01642 return aji_tls_handshake(client); 01643 } 01644 } 01645 #endif 01646 if (!strcmp("stream:features", iks_name(node))) { 01647 features = iks_stream_features(node); 01648 if (client->usesasl) { 01649 if (client->usetls && !aji_is_secure(client)) { 01650 break; 01651 } 01652 if (client->authorized) { 01653 if (features & IKS_STREAM_BIND) { 01654 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); 01655 auth = iks_make_resource_bind(client->jid); 01656 if (auth) { 01657 iks_insert_attrib(auth, "id", client->mid); 01658 ast_aji_increment_mid(client->mid); 01659 ast_aji_send(client, auth); 01660 iks_delete(auth); 01661 } else { 01662 ast_log(LOG_ERROR, "Out of memory.\n"); 01663 break; 01664 } 01665 } 01666 if (features & IKS_STREAM_SESSION) { 01667 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); 01668 auth = iks_make_session(); 01669 if (auth) { 01670 iks_insert_attrib(auth, "id", "auth"); 01671 ast_aji_increment_mid(client->mid); 01672 ast_aji_send(client, auth); 01673 iks_delete(auth); 01674 } else { 01675 ast_log(LOG_ERROR, "Out of memory.\n"); 01676 } 01677 } 01678 } else { 01679 int ret; 01680 if (!client->jid->user) { 01681 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 01682 break; 01683 } 01684 01685 ret = aji_start_sasl(client, features, client->jid->user, client->password); 01686 if (ret != IKS_OK) { 01687 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01688 return IKS_HOOK; 01689 } 01690 break; 01691 } 01692 } 01693 } else if (!strcmp("failure", iks_name(node))) { 01694 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 01695 } else if (!strcmp("success", iks_name(node))) { 01696 client->authorized = 1; 01697 aji_send_header(client, client->jid->server); 01698 } 01699 break; 01700 case IKS_NODE_ERROR: 01701 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01702 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01703 return IKS_HOOK; 01704 break; 01705 case IKS_NODE_STOP: 01706 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01707 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01708 return IKS_HOOK; 01709 break; 01710 } 01711 } else if (client->state != AJI_CONNECTED && client->component) { 01712 switch (type) { 01713 case IKS_NODE_START: 01714 if (client->state == AJI_DISCONNECTED) { 01715 char secret[160], shasum[320], *handshake; 01716 01717 sprintf(secret, "%s%s", pak->id, client->password); 01718 ast_sha1_hash(shasum, secret); 01719 if (ast_asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01720 aji_send_raw(client, handshake); 01721 ast_free(handshake); 01722 } 01723 client->state = AJI_CONNECTING; 01724 if (aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01725 client->state = AJI_CONNECTED; 01726 else 01727 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01728 break; 01729 } 01730 break; 01731 01732 case IKS_NODE_NORMAL: 01733 break; 01734 01735 case IKS_NODE_ERROR: 01736 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01737 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01738 return IKS_HOOK; 01739 01740 case IKS_NODE_STOP: 01741 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01742 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01743 return IKS_HOOK; 01744 } 01745 } 01746 01747 switch (pak->type) { 01748 case IKS_PAK_NONE: 01749 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01750 break; 01751 case IKS_PAK_MESSAGE: 01752 aji_handle_message(client, pak); 01753 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01754 break; 01755 case IKS_PAK_PRESENCE: 01756 aji_handle_presence(client, pak); 01757 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01758 break; 01759 case IKS_PAK_S10N: 01760 aji_handle_subscribe(client, pak); 01761 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01762 break; 01763 case IKS_PAK_IQ: 01764 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01765 aji_handle_iq(client, node); 01766 break; 01767 default: 01768 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01769 break; 01770 } 01771 01772 iks_filter_packet(client->f, pak); 01773 01774 if (node) 01775 iks_delete(node); 01776 01777 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01778 return IKS_OK; 01779 }
| static iks * aji_build_node_config | ( | iks * | pubsub, | |
| const char * | node_type, | |||
| const char * | collection_name | |||
| ) | [static] |
Definition at line 3853 of file res_jabber.c.
Referenced by aji_create_pubsub_node().
03854 { 03855 iks *configure, *x, *field_owner, *field_node_type, *field_node_config, 03856 *field_deliver_payload, *field_persist_items, *field_access_model, 03857 *field_pubsub_collection; 03858 configure = iks_insert(pubsub, "configure"); 03859 x = iks_insert(configure, "x"); 03860 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03861 iks_insert_attrib(x, "type", "submit"); 03862 field_owner = iks_insert(x, "field"); 03863 iks_insert_attrib(field_owner, "var", "FORM_TYPE"); 03864 iks_insert_attrib(field_owner, "type", "hidden"); 03865 iks_insert_cdata(iks_insert(field_owner, "value"), 03866 "http://jabber.org/protocol/pubsub#owner", 39); 03867 if (node_type) { 03868 field_node_type = iks_insert(x, "field"); 03869 iks_insert_attrib(field_node_type, "var", "pubsub#node_type"); 03870 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type)); 03871 } 03872 field_node_config = iks_insert(x, "field"); 03873 iks_insert_attrib(field_node_config, "var", "FORM_TYPE"); 03874 iks_insert_attrib(field_node_config, "type", "hidden"); 03875 iks_insert_cdata(iks_insert(field_node_config, "value"), 03876 "http://jabber.org/protocol/pubsub#node_config", 45); 03877 field_deliver_payload = iks_insert(x, "field"); 03878 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads"); 03879 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1); 03880 field_persist_items = iks_insert(x, "field"); 03881 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items"); 03882 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1); 03883 field_access_model = iks_insert(x, "field"); 03884 iks_insert_attrib(field_access_model, "var", "pubsub#access_model"); 03885 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9); 03886 if (node_type && !strcasecmp(node_type, "leaf")) { 03887 field_pubsub_collection = iks_insert(x, "field"); 03888 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection"); 03889 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name, 03890 strlen(collection_name)); 03891 } 03892 return configure; 03893 }
| 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 3583 of file res_jabber.c.
References aji_pubsub_iq_create().
Referenced by aji_pubsub_purge_nodes(), and aji_request_pubsub_nodes().
03584 { 03585 iks *request = aji_pubsub_iq_create(client, "get"); 03586 iks *query; 03587 query = iks_insert(request, "query"); 03588 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 03589 if (collection) { 03590 iks_insert_attrib(query, "node", collection); 03591 } 03592 return request; 03593 }
| static iks * aji_build_publish_skeleton | ( | struct aji_client * | client, | |
| const char * | node, | |||
| const char * | event_type, | |||
| unsigned int | cachable | |||
| ) | [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 3393 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, AST_DEVSTATE_NOT_CACHABLE, and ast_test_flag.
Referenced by aji_publish_device_state(), and aji_publish_mwi().
03395 { 03396 iks *request = aji_pubsub_iq_create(client, "set"); 03397 iks *pubsub, *publish, *item; 03398 pubsub = iks_insert(request, "pubsub"); 03399 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03400 publish = iks_insert(pubsub, "publish"); 03401 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03402 iks_insert_attrib(publish, "node", node); 03403 } else { 03404 iks_insert_attrib(publish, "node", event_type); 03405 } 03406 item = iks_insert(publish, "item"); 03407 iks_insert_attrib(item, "id", node); 03408 03409 if (cachable == AST_DEVSTATE_NOT_CACHABLE) { 03410 iks *options, *x, *field_form_type, *field_persist; 03411 03412 options = iks_insert(pubsub, "publish-options"); 03413 x = iks_insert(options, "x"); 03414 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03415 iks_insert_attrib(x, "type", "submit"); 03416 field_form_type = iks_insert(x, "field"); 03417 iks_insert_attrib(field_form_type, "var", "FORM_TYPE"); 03418 iks_insert_attrib(field_form_type, "type", "hidden"); 03419 iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0); 03420 field_persist = iks_insert(x, "field"); 03421 iks_insert_attrib(field_persist, "var", "pubsub#persist_items"); 03422 iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1); 03423 } 03424 03425 return item; 03426 }
| 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 3901 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.
03902 { 03903 struct aji_client *client; 03904 const char *name; 03905 const char *collection_name; 03906 03907 switch (cmd) { 03908 case CLI_INIT: 03909 e->command = "jabber create collection"; 03910 e->usage = 03911 "Usage: jabber create collection <connection> <collection>\n" 03912 " Creates a PubSub collection node using the account\n" 03913 " as configured in jabber.conf.\n"; 03914 return NULL; 03915 case CLI_GENERATE: 03916 return NULL; 03917 } 03918 03919 if (a->argc != 5) { 03920 return CLI_SHOWUSAGE; 03921 } 03922 name = a->argv[3]; 03923 collection_name = a->argv[4]; 03924 03925 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03926 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03927 return CLI_FAILURE; 03928 } 03929 03930 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03931 aji_create_pubsub_collection(client, collection_name); 03932 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03933 return CLI_SUCCESS; 03934 }
| 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 3940 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.
03941 { 03942 struct aji_client *client; 03943 const char *name; 03944 const char *collection_name; 03945 const char *leaf_name; 03946 03947 switch (cmd) { 03948 case CLI_INIT: 03949 e->command = "jabber create leaf"; 03950 e->usage = 03951 "Usage: jabber create leaf <connection> <collection> <leaf>\n" 03952 " Creates a PubSub leaf node using the account\n" 03953 " as configured in jabber.conf.\n"; 03954 return NULL; 03955 case CLI_GENERATE: 03956 return NULL; 03957 } 03958 03959 if (a->argc != 6) { 03960 return CLI_SHOWUSAGE; 03961 } 03962 name = a->argv[3]; 03963 collection_name = a->argv[4]; 03964 leaf_name = a->argv[5]; 03965 03966 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03967 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03968 return CLI_FAILURE; 03969 } 03970 03971 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03972 aji_create_pubsub_leaf(client, collection_name, leaf_name); 03973 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03974 return CLI_SUCCESS; 03975 }
| 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 3754 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.
03756 { 03757 struct aji_client *client; 03758 const char *name; 03759 03760 switch (cmd) { 03761 case CLI_INIT: 03762 e->command = "jabber delete node"; 03763 e->usage = 03764 "Usage: jabber delete node <connection> <node>\n" 03765 " Deletes a node on PubSub server\n" 03766 " as configured in jabber.conf.\n"; 03767 return NULL; 03768 case CLI_GENERATE: 03769 return NULL; 03770 } 03771 03772 if (a->argc != 5) { 03773 return CLI_SHOWUSAGE; 03774 } 03775 name = a->argv[3]; 03776 03777 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03778 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03779 return CLI_FAILURE; 03780 } 03781 aji_delete_pubsub_node(client, a->argv[4]); 03782 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03783 return CLI_SUCCESS; 03784 }
| 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 3629 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.
03631 { 03632 struct aji_client *client; 03633 const char *name = NULL; 03634 const char *collection = NULL; 03635 03636 switch (cmd) { 03637 case CLI_INIT: 03638 e->command = "jabber list nodes"; 03639 e->usage = 03640 "Usage: jabber list nodes <connection> [collection]\n" 03641 " Lists the user's nodes on the respective connection\n" 03642 " ([connection] as configured in jabber.conf.)\n"; 03643 return NULL; 03644 case CLI_GENERATE: 03645 return NULL; 03646 } 03647 03648 if (a->argc > 5 || a->argc < 4) { 03649 return CLI_SHOWUSAGE; 03650 } else if (a->argc == 4 || a->argc == 5) { 03651 name = a->argv[3]; 03652 } 03653 if (a->argc == 5) { 03654 collection = a->argv[4]; 03655 } 03656 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03657 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03658 return CLI_FAILURE; 03659 } 03660 03661 ast_cli(a->fd, "Listing pubsub nodes.\n"); 03662 aji_request_pubsub_nodes(client, collection); 03663 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03664 return CLI_SUCCESS; 03665 }
| 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 3674 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.
03676 { 03677 struct aji_client *client; 03678 const char *name; 03679 03680 switch (cmd) { 03681 case CLI_INIT: 03682 e->command = "jabber purge nodes"; 03683 e->usage = 03684 "Usage: jabber purge nodes <connection> <node>\n" 03685 " Purges nodes on PubSub server\n" 03686 " as configured in jabber.conf.\n"; 03687 return NULL; 03688 case CLI_GENERATE: 03689 return NULL; 03690 } 03691 03692 if (a->argc != 5) { 03693 return CLI_SHOWUSAGE; 03694 } 03695 name = a->argv[3]; 03696 03697 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03698 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03699 return CLI_FAILURE; 03700 } 03701 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03702 aji_pubsub_purge_nodes(client, a->argv[4]); 03703 } else { 03704 aji_delete_pubsub_node(client, a->argv[4]); 03705 } 03706 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03707 return CLI_SUCCESS; 03708 }
| static int aji_client_connect | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 3087 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().
03088 { 03089 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03090 int res = IKS_FILTER_PASS; 03091 03092 if (client) { 03093 if (client->state == AJI_DISCONNECTED) { 03094 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); 03095 client->state = AJI_CONNECTING; 03096 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 03097 if (!client->component) { /*client*/ 03098 aji_get_roster(client); 03099 } 03100 if (client->distribute_events) { 03101 aji_init_event_distribution(client); 03102 } 03103 03104 iks_filter_remove_hook(client->f, aji_client_connect); 03105 /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ 03106 res = IKS_FILTER_EAT; 03107 } 03108 } else { 03109 ast_log(LOG_ERROR, "Out of memory.\n"); 03110 } 03111 03112 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03113 return res; 03114 }
| static int aji_client_info_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2000 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().
02001 { 02002 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02003 struct aji_resource *resource = NULL; 02004 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02005 02006 if (!buddy) { 02007 ast_log(LOG_NOTICE, "JABBER: Received client info from unknown buddy: %s.\n", pak->from->full); 02008 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02009 return IKS_FILTER_EAT; 02010 } 02011 02012 resource = aji_find_resource(buddy, pak->from->resource); 02013 if (pak->subtype == IKS_TYPE_RESULT) { 02014 if (!resource) { 02015 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02016 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02017 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02018 return IKS_FILTER_EAT; 02019 } 02020 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02021 resource->cap->jingle = 1; 02022 } else { 02023 resource->cap->jingle = 0; 02024 } 02025 } else if (pak->subtype == IKS_TYPE_GET) { 02026 iks *iq, *disco, *ident, *google, *query; 02027 iq = iks_new("iq"); 02028 query = iks_new("query"); 02029 ident = iks_new("identity"); 02030 disco = iks_new("feature"); 02031 google = iks_new("feature"); 02032 if (iq && ident && disco && google) { 02033 iks_insert_attrib(iq, "from", client->jid->full); 02034 iks_insert_attrib(iq, "to", pak->from->full); 02035 iks_insert_attrib(iq, "type", "result"); 02036 iks_insert_attrib(iq, "id", pak->id); 02037 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02038 iks_insert_attrib(ident, "category", "client"); 02039 iks_insert_attrib(ident, "type", "pc"); 02040 iks_insert_attrib(ident, "name", "asterisk"); 02041 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 02042 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 02043 iks_insert_node(iq, query); 02044 iks_insert_node(query, ident); 02045 iks_insert_node(query, google); 02046 iks_insert_node(query, disco); 02047 ast_aji_send(client, iq); 02048 } else { 02049 ast_log(LOG_ERROR, "Out of Memory.\n"); 02050 } 02051 02052 iks_delete(iq); 02053 iks_delete(query); 02054 iks_delete(ident); 02055 iks_delete(google); 02056 iks_delete(disco); 02057 } else if (pak->subtype == IKS_TYPE_ERROR) { 02058 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 02059 } 02060 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02061 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02062 return IKS_FILTER_EAT; 02063 }
| 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 3329 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().
03330 { 03331 iks *modify_affiliates = aji_pubsub_iq_create(client, "set"); 03332 iks *pubsub, *affiliations, *affiliate; 03333 pubsub = iks_insert(modify_affiliates, "pubsub"); 03334 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03335 affiliations = iks_insert(pubsub, "affiliations"); 03336 iks_insert_attrib(affiliations, "node", node); 03337 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03338 ASTOBJ_RDLOCK(iterator); 03339 affiliate = iks_insert(affiliations, "affiliation"); 03340 iks_insert_attrib(affiliate, "jid", iterator->name); 03341 iks_insert_attrib(affiliate, "affiliation", "owner"); 03342 ASTOBJ_UNLOCK(iterator); 03343 }); 03344 ast_aji_send(client, modify_affiliates); 03345 iks_delete(modify_affiliates); 03346 }
| static int aji_create_buddy | ( | char * | label, | |
| struct aji_client * | client | |||
| ) | [static] |
load config file.
Definition at line 4487 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 4233 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(), ast_aji_client_destroy(), ast_asprintf, 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::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::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::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().
04234 { 04235 char *resource; 04236 struct aji_client *client = NULL; 04237 int flag = 0; 04238 04239 client = ASTOBJ_CONTAINER_FIND(&clients, label); 04240 if (!client) { 04241 flag = 1; 04242 client = ast_calloc(1, sizeof(*client)); 04243 if (!client) { 04244 ast_log(LOG_ERROR, "Out of memory!\n"); 04245 return 0; 04246 } 04247 ASTOBJ_INIT(client); 04248 ASTOBJ_WRLOCK(client); 04249 ASTOBJ_CONTAINER_INIT(&client->buddies); 04250 } else { 04251 ASTOBJ_WRLOCK(client); 04252 ASTOBJ_UNMARK(client); 04253 } 04254 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 04255 ast_copy_string(client->name, label, sizeof(client->name)); 04256 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 04257 04258 /* Set default values for the client object */ 04259 client->debug = debug; 04260 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 04261 client->port = 5222; 04262 client->usetls = 1; 04263 client->usesasl = 1; 04264 client->forcessl = 0; 04265 client->keepalive = 1; 04266 client->timeout = 50; 04267 client->message_timeout = 5; 04268 client->distribute_events = 0; 04269 AST_LIST_HEAD_INIT(&client->messages); 04270 client->component = 0; 04271 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 04272 client->priority = 0; 04273 client->status = IKS_SHOW_AVAILABLE; 04274 04275 if (flag) { 04276 client->authorized = 0; 04277 client->state = AJI_DISCONNECTED; 04278 } 04279 while (var) { 04280 if (!strcasecmp(var->name, "username")) { 04281 ast_copy_string(client->user, var->value, sizeof(client->user)); 04282 } else if (!strcasecmp(var->name, "serverhost")) { 04283 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 04284 } else if (!strcasecmp(var->name, "secret")) { 04285 ast_copy_string(client->password, var->value, sizeof(client->password)); 04286 } else if (!strcasecmp(var->name, "statusmessage")) { 04287 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 04288 } else if (!strcasecmp(var->name, "port")) { 04289 client->port = atoi(var->value); 04290 } else if (!strcasecmp(var->name, "timeout")) { 04291 client->message_timeout = atoi(var->value); 04292 } else if (!strcasecmp(var->name, "debug")) { 04293 client->debug = (ast_false(var->value)) ? 0 : 1; 04294 } else if (!strcasecmp(var->name, "type")) { 04295 if (!strcasecmp(var->value, "component")) { 04296 client->component = 1; 04297 if (client->distribute_events) { 04298 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04299 client->distribute_events = 0; 04300 } 04301 } 04302 } else if (!strcasecmp(var->name, "distribute_events")) { 04303 if (ast_true(var->value)) { 04304 if (client->component) { 04305 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04306 } else { 04307 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) { 04308 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n"); 04309 } else { 04310 ast_set_flag(&pubsubflags, AJI_PUBSUB); 04311 client->distribute_events = 1; 04312 } 04313 } 04314 } 04315 } else if (!strcasecmp(var->name, "pubsub_node")) { 04316 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node)); 04317 } else if (!strcasecmp(var->name, "usetls")) { 04318 client->usetls = (ast_false(var->value)) ? 0 : 1; 04319 } else if (!strcasecmp(var->name, "usesasl")) { 04320 client->usesasl = (ast_false(var->value)) ? 0 : 1; 04321 } else if (!strcasecmp(var->name, "forceoldssl")) { 04322 client->forcessl = (ast_false(var->value)) ? 0 : 1; 04323 } else if (!strcasecmp(var->name, "keepalive")) { 04324 client->keepalive = (ast_false(var->value)) ? 0 : 1; 04325 } else if (!strcasecmp(var->name, "autoprune")) { 04326 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 04327 } else if (!strcasecmp(var->name, "autoregister")) { 04328 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 04329 } else if (!strcasecmp(var->name, "auth_policy")) { 04330 if (!strcasecmp(var->value, "accept")) { 04331 ast_set_flag(&client->flags, AJI_AUTOACCEPT); 04332 } else { 04333 ast_clear_flag(&client->flags, AJI_AUTOACCEPT); 04334 } 04335 } else if (!strcasecmp(var->name, "buddy")) { 04336 aji_create_buddy((char *)var->value, client); 04337 } else if (!strcasecmp(var->name, "priority")) { 04338 client->priority = atoi(var->value); 04339 } else if (!strcasecmp(var->name, "status")) { 04340 if (!strcasecmp(var->value, "unavailable")) { 04341 client->status = IKS_SHOW_UNAVAILABLE; 04342 } else if (!strcasecmp(var->value, "available") 04343 || !strcasecmp(var->value, "online")) { 04344 client->status = IKS_SHOW_AVAILABLE; 04345 } else if (!strcasecmp(var->value, "chat") 04346 || !strcasecmp(var->value, "chatty")) { 04347 client->status = IKS_SHOW_CHAT; 04348 } else if (!strcasecmp(var->value, "away")) { 04349 client->status = IKS_SHOW_AWAY; 04350 } else if (!strcasecmp(var->value, "xa") 04351 || !strcasecmp(var->value, "xaway")) { 04352 client->status = IKS_SHOW_XA; 04353 } else if (!strcasecmp(var->value, "dnd")) { 04354 client->status = IKS_SHOW_DND; 04355 } else if (!strcasecmp(var->value, "invisible")) { 04356 #ifdef IKS_SHOW_INVISIBLE 04357 client->status = IKS_SHOW_INVISIBLE; 04358 #else 04359 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 04360 client->status = IKS_SHOW_DND; 04361 #endif 04362 } else { 04363 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 04364 } 04365 } 04366 /* no transport support in this version */ 04367 /* else if (!strcasecmp(var->name, "transport")) 04368 aji_create_transport(var->value, client); 04369 */ 04370 var = var->next; 04371 } 04372 if (!flag) { 04373 ASTOBJ_UNLOCK(client); 04374 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04375 return 1; 04376 } 04377 04378 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 04379 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 04380 if (!client->p) { 04381 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 04382 return 0; 04383 } 04384 client->stack = iks_stack_new(8192, 8192); 04385 if (!client->stack) { 04386 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 04387 return 0; 04388 } 04389 client->f = iks_filter_new(); 04390 if (!client->f) { 04391 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 04392 return 0; 04393 } 04394 if (!strchr(client->user, '/') && !client->component) { /*client */ 04395 if (ast_asprintf(&resource, "%s/asterisk", client->user) >= 0) { 04396 client->jid = iks_id_new(client->stack, resource); 04397 ast_free(resource); 04398 } 04399 } else { 04400 client->jid = iks_id_new(client->stack, client->user); 04401 } 04402 if (client->component) { 04403 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04404 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 04405 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); 04406 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); 04407 } else { 04408 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04409 } 04410 04411 iks_set_log_hook(client->p, aji_log_hook); 04412 ASTOBJ_UNLOCK(client); 04413 ASTOBJ_CONTAINER_LINK(&clients, client); 04414 return 1; 04415 }
| 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 3809 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_collection(), and aji_handle_pubsub_error().
03811 { 03812 aji_create_pubsub_node(client, "collection", collection_name, NULL); 03813 }
| 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 3822 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_leafnode(), and aji_handle_pubsub_error().
03824 { 03825 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name); 03826 }
| 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 3835 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().
03837 { 03838 iks *node = aji_pubsub_iq_create(client, "set"); 03839 iks *pubsub, *create; 03840 pubsub = iks_insert(node, "pubsub"); 03841 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03842 create = iks_insert(pubsub, "create"); 03843 iks_insert_attrib(create, "node", name); 03844 aji_build_node_config(pubsub, node_type, collection_name); 03845 ast_aji_send(client, node); 03846 aji_create_affiliations(client, name); 03847 iks_delete(node); 03848 return 0; 03849 }
| 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 3727 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().
03728 { 03729 03730 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03731 iks *item = NULL; 03732 if (iks_has_children(pak->query)) { 03733 item = iks_first_tag(pak->query); 03734 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial, 03735 iks_find_attrib(item, "node")); 03736 while ((item = iks_next_tag(item))) { 03737 aji_delete_pubsub_node(client, iks_find_attrib(item, "node")); 03738 } 03739 } 03740 if (item) { 03741 iks_delete(item); 03742 } 03743 return IKS_FILTER_EAT; 03744 }
| 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 3792 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().
03793 { 03794 iks *request = aji_pubsub_iq_create(client, "set"); 03795 iks *pubsub, *delete; 03796 pubsub = iks_insert(request, "pubsub"); 03797 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03798 delete = iks_insert(pubsub, "delete"); 03799 iks_insert_attrib(delete, "node", node_name); 03800 ast_aji_send(client, request); 03801 }
| 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 3206 of file res_jabber.c.
References aji_publish_device_state(), ast_aji_client_destroy(), 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_CACHABLE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, and LOG_DEBUG.
Referenced by aji_init_event_distribution().
03207 { 03208 const char *device; 03209 const char *device_state; 03210 unsigned int cachable; 03211 struct aji_client *client; 03212 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03213 { 03214 /* If the event didn't originate from this server, don't send it back out. */ 03215 ast_log(LOG_DEBUG, "Returning here\n"); 03216 return; 03217 } 03218 03219 client = ASTOBJ_REF((struct aji_client *) data); 03220 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); 03221 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); 03222 cachable = ast_event_get_ie_uint(ast_event, AST_EVENT_IE_CACHABLE); 03223 aji_publish_device_state(client, device, device_state, cachable); 03224 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03225 }
| static int aji_dinfo_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2072 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().
02073 { 02074 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02075 char *node = NULL; 02076 struct aji_resource *resource = NULL; 02077 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02078 02079 if (!buddy) { 02080 ast_log(LOG_NOTICE, "JABBER: Received client info from unknown buddy: %s.\n", pak->from->full); 02081 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02082 return IKS_FILTER_EAT; 02083 } 02084 02085 if (pak->subtype == IKS_TYPE_ERROR) { 02086 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 02087 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02088 return IKS_FILTER_EAT; 02089 } 02090 resource = aji_find_resource(buddy, pak->from->resource); 02091 if (pak->subtype == IKS_TYPE_RESULT) { 02092 if (!resource) { 02093 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02094 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02095 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02096 return IKS_FILTER_EAT; 02097 } 02098 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02099 resource->cap->jingle = 1; 02100 } else { 02101 resource->cap->jingle = 0; 02102 } 02103 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 02104 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 02105 02106 iq = iks_new("iq"); 02107 query = iks_new("query"); 02108 identity = iks_new("identity"); 02109 disco = iks_new("feature"); 02110 reg = iks_new("feature"); 02111 commands = iks_new("feature"); 02112 gateway = iks_new("feature"); 02113 version = iks_new("feature"); 02114 vcard = iks_new("feature"); 02115 search = iks_new("feature"); 02116 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 02117 iks_insert_attrib(iq, "from", client->user); 02118 iks_insert_attrib(iq, "to", pak->from->full); 02119 iks_insert_attrib(iq, "id", pak->id); 02120 iks_insert_attrib(iq, "type", "result"); 02121 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02122 iks_insert_attrib(identity, "category", "gateway"); 02123 iks_insert_attrib(identity, "type", "pstn"); 02124 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 02125 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 02126 iks_insert_attrib(reg, "var", "jabber:iq:register"); 02127 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 02128 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 02129 iks_insert_attrib(version, "var", "jabber:iq:version"); 02130 iks_insert_attrib(vcard, "var", "vcard-temp"); 02131 iks_insert_attrib(search, "var", "jabber:iq:search"); 02132 02133 iks_insert_node(iq, query); 02134 iks_insert_node(query, identity); 02135 iks_insert_node(query, disco); 02136 iks_insert_node(query, reg); 02137 iks_insert_node(query, commands); 02138 iks_insert_node(query, gateway); 02139 iks_insert_node(query, version); 02140 iks_insert_node(query, vcard); 02141 iks_insert_node(query, search); 02142 ast_aji_send(client, iq); 02143 } else { 02144 ast_log(LOG_ERROR, "Out of memory.\n"); 02145 } 02146 02147 iks_delete(iq); 02148 iks_delete(query); 02149 iks_delete(identity); 02150 iks_delete(disco); 02151 iks_delete(reg); 02152 iks_delete(commands); 02153 iks_delete(gateway); 02154 iks_delete(version); 02155 iks_delete(vcard); 02156 iks_delete(search); 02157 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 02158 iks *iq, *query, *confirm; 02159 iq = iks_new("iq"); 02160 query = iks_new("query"); 02161 confirm = iks_new("item"); 02162 02163 if (iq && query && confirm && client) { 02164 iks_insert_attrib(iq, "from", client->user); 02165 iks_insert_attrib(iq, "to", pak->from->full); 02166 iks_insert_attrib(iq, "id", pak->id); 02167 iks_insert_attrib(iq, "type", "result"); 02168 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 02169 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 02170 iks_insert_attrib(confirm, "node", "confirmaccount"); 02171 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 02172 iks_insert_attrib(confirm, "jid", client->user); 02173 iks_insert_node(iq, query); 02174 iks_insert_node(query, confirm); 02175 ast_aji_send(client, iq); 02176 } else { 02177 ast_log(LOG_ERROR, "Out of memory.\n"); 02178 } 02179 02180 iks_delete(iq); 02181 iks_delete(query); 02182 iks_delete(confirm); 02183 02184 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 02185 iks *iq, *query, *feature; 02186 02187 iq = iks_new("iq"); 02188 query = iks_new("query"); 02189 feature = iks_new("feature"); 02190 02191 if (iq && query && feature && client) { 02192 iks_insert_attrib(iq, "from", client->user); 02193 iks_insert_attrib(iq, "to", pak->from->full); 02194 iks_insert_attrib(iq, "id", pak->id); 02195 iks_insert_attrib(iq, "type", "result"); 02196 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02197 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 02198 iks_insert_node(iq, query); 02199 iks_insert_node(query, feature); 02200 ast_aji_send(client, iq); 02201 } else { 02202 ast_log(LOG_ERROR, "Out of memory.\n"); 02203 } 02204 02205 iks_delete(iq); 02206 iks_delete(query); 02207 iks_delete(feature); 02208 } 02209 02210 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02211 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02212 return IKS_FILTER_EAT; 02213 }
| static int aji_ditems_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1903 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().
01904 { 01905 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01906 char *node = NULL; 01907 01908 if (!(node = iks_find_attrib(pak->query, "node"))) { 01909 iks *iq = NULL, *query = NULL, *item = NULL; 01910 iq = iks_new("iq"); 01911 query = iks_new("query"); 01912 item = iks_new("item"); 01913 01914 if (iq && query && item) { 01915 iks_insert_attrib(iq, "from", client->user); 01916 iks_insert_attrib(iq, "to", pak->from->full); 01917 iks_insert_attrib(iq, "id", pak->id); 01918 iks_insert_attrib(iq, "type", "result"); 01919 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01920 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01921 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01922 iks_insert_attrib(item, "jid", client->user); 01923 01924 iks_insert_node(iq, query); 01925 iks_insert_node(query, item); 01926 ast_aji_send(client, iq); 01927 } else { 01928 ast_log(LOG_ERROR, "Out of memory.\n"); 01929 } 01930 01931 iks_delete(iq); 01932 iks_delete(query); 01933 iks_delete(item); 01934 01935 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01936 iks *iq, *query, *confirm; 01937 iq = iks_new("iq"); 01938 query = iks_new("query"); 01939 confirm = iks_new("item"); 01940 if (iq && query && confirm && client) { 01941 iks_insert_attrib(iq, "from", client->user); 01942 iks_insert_attrib(iq, "to", pak->from->full); 01943 iks_insert_attrib(iq, "id", pak->id); 01944 iks_insert_attrib(iq, "type", "result"); 01945 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01946 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01947 iks_insert_attrib(confirm, "node", "confirmaccount"); 01948 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01949 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01950 01951 iks_insert_node(iq, query); 01952 iks_insert_node(query, confirm); 01953 ast_aji_send(client, iq); 01954 } else { 01955 ast_log(LOG_ERROR, "Out of memory.\n"); 01956 } 01957 01958 iks_delete(iq); 01959 iks_delete(query); 01960 iks_delete(confirm); 01961 01962 } else if (!strcasecmp(node, "confirmaccount")) { 01963 iks *iq = NULL, *query = NULL, *feature = NULL; 01964 01965 iq = iks_new("iq"); 01966 query = iks_new("query"); 01967 feature = iks_new("feature"); 01968 01969 if (iq && query && feature && client) { 01970 iks_insert_attrib(iq, "from", client->user); 01971 iks_insert_attrib(iq, "to", pak->from->full); 01972 iks_insert_attrib(iq, "id", pak->id); 01973 iks_insert_attrib(iq, "type", "result"); 01974 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01975 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01976 iks_insert_node(iq, query); 01977 iks_insert_node(query, feature); 01978 ast_aji_send(client, iq); 01979 } else { 01980 ast_log(LOG_ERROR, "Out of memory.\n"); 01981 } 01982 01983 iks_delete(iq); 01984 iks_delete(query); 01985 iks_delete(feature); 01986 } 01987 01988 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01989 return IKS_FILTER_EAT; 01990 01991 }
| static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4114 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.
04115 { 04116 switch (cmd) { 04117 case CLI_INIT: 04118 e->command = "jabber reload"; 04119 e->usage = 04120 "Usage: jabber reload\n" 04121 " Reloads the Jabber module.\n"; 04122 return NULL; 04123 case CLI_GENERATE: 04124 return NULL; 04125 } 04126 04127 aji_reload(1); 04128 ast_cli(a->fd, "Jabber Reloaded.\n"); 04129 return CLI_SUCCESS; 04130 }
| static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4072 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.
04073 { 04074 switch (cmd) { 04075 case CLI_INIT: 04076 e->command = "jabber set debug {on|off}"; 04077 e->usage = 04078 "Usage: jabber set debug {on|off}\n" 04079 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 04080 return NULL; 04081 case CLI_GENERATE: 04082 return NULL; 04083 } 04084 04085 if (a->argc != e->args) { 04086 return CLI_SHOWUSAGE; 04087 } 04088 04089 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 04090 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04091 ASTOBJ_RDLOCK(iterator); 04092 iterator->debug = 1; 04093 ASTOBJ_UNLOCK(iterator); 04094 }); 04095 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 04096 return CLI_SUCCESS; 04097 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 04098 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04099 ASTOBJ_RDLOCK(iterator); 04100 iterator->debug = 0; 04101 ASTOBJ_UNLOCK(iterator); 04102 }); 04103 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 04104 return CLI_SUCCESS; 04105 } 04106 return CLI_SHOWUSAGE; /* defaults to invalid */ 04107 }
| static int aji_filter_roster | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2950 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().
02951 { 02952 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02953 int flag = 0; 02954 iks *x = NULL; 02955 struct aji_buddy *buddy; 02956 02957 client->state = AJI_CONNECTED; 02958 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02959 ASTOBJ_RDLOCK(iterator); 02960 x = iks_child(pak->query); 02961 flag = 0; 02962 while (x) { 02963 if (!iks_strcmp(iks_name(x), "item")) { 02964 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02965 flag = 1; 02966 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02967 } 02968 } 02969 x = iks_next(x); 02970 } 02971 if (!flag) { 02972 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02973 } 02974 iks_delete(x); 02975 02976 ASTOBJ_UNLOCK(iterator); 02977 }); 02978 02979 x = iks_child(pak->query); 02980 while (x) { 02981 flag = 0; 02982 if (iks_strcmp(iks_name(x), "item") == 0) { 02983 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02984 ASTOBJ_RDLOCK(iterator); 02985 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02986 flag = 1; 02987 ASTOBJ_UNLOCK(iterator); 02988 }); 02989 02990 if (flag) { 02991 /* found buddy, don't create a new one */ 02992 x = iks_next(x); 02993 continue; 02994 } 02995 02996 buddy = ast_calloc(1, sizeof(*buddy)); 02997 if (!buddy) { 02998 ast_log(LOG_WARNING, "Out of memory\n"); 02999 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03000 return 0; 03001 } 03002 ASTOBJ_INIT(buddy); 03003 ASTOBJ_WRLOCK(buddy); 03004 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 03005 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 03006 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 03007 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 03008 ASTOBJ_MARK(buddy); 03009 } else if (ast_test_flag(&client->flags, AJI_AUTOREGISTER)) { 03010 if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 03011 /* subscribe to buddy's presence only 03012 if we really need to */ 03013 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 03014 } 03015 } 03016 ASTOBJ_UNLOCK(buddy); 03017 if (buddy) { 03018 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 03019 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 03020 } 03021 } 03022 x = iks_next(x); 03023 } 03024 03025 iks_delete(x); 03026 aji_pruneregister(client); 03027 03028 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03029 return IKS_FILTER_EAT; 03030 }
| static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
| char * | name | |||
| ) | [static, read] |
Definition at line 544 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().
| static struct aji_version* aji_find_version | ( | char * | node, | |
| char * | version, | |||
| ikspak * | pak | |||
| ) | [static, read] |
Definition at line 472 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().
00473 { 00474 struct aji_capabilities *list = NULL; 00475 struct aji_version *res = NULL; 00476 00477 list = capabilities; 00478 00479 if (!node) { 00480 node = pak->from->full; 00481 } 00482 if (!version) { 00483 version = "none supplied."; 00484 } 00485 while (list) { 00486 if (!strcasecmp(list->node, node)) { 00487 res = list->versions; 00488 while(res) { 00489 if (!strcasecmp(res->version, version)) { 00490 return res; 00491 } 00492 res = res->next; 00493 } 00494 /* Specified version not found. Let's add it to 00495 this node in our capabilities list */ 00496 if (!res) { 00497 res = ast_malloc(sizeof(*res)); 00498 if (!res) { 00499 ast_log(LOG_ERROR, "Out of memory!\n"); 00500 return NULL; 00501 } 00502 res->jingle = 0; 00503 res->parent = list; 00504 ast_copy_string(res->version, version, sizeof(res->version)); 00505 res->next = list->versions; 00506 list->versions = res; 00507 return res; 00508 } 00509 } 00510 list = list->next; 00511 } 00512 /* Specified node not found. Let's add it our capabilities list */ 00513 if (!list) { 00514 list = ast_malloc(sizeof(*list)); 00515 if (!list) { 00516 ast_log(LOG_ERROR, "Out of memory!\n"); 00517 return NULL; 00518 } 00519 res = ast_malloc(sizeof(*res)); 00520 if (!res) { 00521 ast_log(LOG_ERROR, "Out of memory!\n"); 00522 ast_free(list); 00523 return NULL; 00524 } 00525 ast_copy_string(list->node, node, sizeof(list->node)); 00526 ast_copy_string(res->version, version, sizeof(res->version)); 00527 res->jingle = 0; 00528 res->parent = list; 00529 res->next = NULL; 00530 list->versions = res; 00531 list->next = capabilities; 00532 capabilities = list; 00533 } 00534 return res; 00535 }
| static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Definition at line 3064 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().
03065 { 03066 iks *roster = NULL; 03067 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 03068 03069 if (roster) { 03070 iks_insert_attrib(roster, "id", "roster"); 03071 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 03072 ast_aji_send(client, roster); 03073 } 03074 03075 iks_delete(roster); 03076 03077 return 1; 03078 }
| static void aji_handle_iq | ( | struct aji_client * | client, | |
| iks * | node | |||
| ) | [static] |
Definition at line 2222 of file res_jabber.c.
Referenced by aji_act_hook().
| static void aji_handle_message | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2234 of file res_jabber.c.
References aji_message::arrived, ast_calloc, ast_cond_broadcast, ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvnow(), delete_old_messages(), aji_message::from, aji_message::id, LOG_ERROR, aji_message::message, and aji_client::name.
Referenced by aji_act_hook().
02235 { 02236 struct aji_message *insert; 02237 int deleted = 0; 02238 02239 ast_debug(3, "client %s received a message\n", client->name); 02240 02241 if (!(insert = ast_calloc(1, sizeof(*insert)))) { 02242 return; 02243 } 02244 02245 insert->arrived = ast_tvnow(); 02246 02247 /* wake up threads waiting for messages */ 02248 ast_mutex_lock(&messagelock); 02249 ast_cond_broadcast(&message_received_condition); 02250 ast_mutex_unlock(&messagelock); 02251 02252 if (iks_find_cdata(pak->x, "body")) { 02253 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 02254 } 02255 if (pak->id) { 02256 ast_copy_string(insert->id, pak->id, sizeof(insert->id)); 02257 } 02258 if (pak->from){ 02259 /* insert will furtherly be added to message list */ 02260 insert->from = ast_strdup(pak->from->full); 02261 if (!insert->from) { 02262 ast_free(insert); 02263 ast_log(LOG_ERROR, "Memory allocation failure\n"); 02264 return; 02265 } 02266 ast_debug(3, "message comes from %s\n", insert->from); 02267 } 02268 02269 /* remove old messages received from this JID 02270 * and insert received message */ 02271 deleted = delete_old_messages(client, pak->from->partial); 02272 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 02273 AST_LIST_LOCK(&client->messages); 02274 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 02275 AST_LIST_UNLOCK(&client->messages); 02276 }
| static void aji_handle_presence | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2284 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, 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().
02285 { 02286 int status, priority; 02287 struct aji_buddy *buddy; 02288 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02289 char *ver, *node, *descrip, *type; 02290 02291 if (client->state != AJI_CONNECTED) 02292 aji_create_buddy(pak->from->partial, client); 02293 02294 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02295 if (!buddy && pak->from->partial) { 02296 /* allow our jid to be used to log in with another resource */ 02297 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02298 aji_create_buddy(pak->from->partial, client); 02299 else 02300 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02301 return; 02302 } 02303 type = iks_find_attrib(pak->x, "type"); 02304 if (client->component && type &&!strcasecmp("probe", type)) { 02305 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02306 ast_verbose("what i was looking for \n"); 02307 } 02308 ASTOBJ_WRLOCK(buddy); 02309 status = (pak->show) ? pak->show : 6; 02310 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02311 tmp = buddy->resources; 02312 descrip = ast_strdup(iks_find_cdata(pak->x, "status")); 02313 02314 while (tmp && pak->from->resource) { 02315 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02316 tmp->status = status; 02317 if (tmp->description) { 02318 ast_free(tmp->description); 02319 } 02320 tmp->description = descrip; 02321 found = tmp; 02322 if (status == 6) { /* Sign off Destroy resource */ 02323 if (last && found->next) { 02324 last->next = found->next; 02325 } else if (!last) { 02326 if (found->next) { 02327 buddy->resources = found->next; 02328 } else { 02329 buddy->resources = NULL; 02330 } 02331 } else if (!found->next) { 02332 if (last) { 02333 last->next = NULL; 02334 } else { 02335 buddy->resources = NULL; 02336 } 02337 } 02338 ast_free(found); 02339 found = NULL; 02340 break; 02341 } 02342 /* resource list is sorted by descending priority */ 02343 if (tmp->priority != priority) { 02344 found->priority = priority; 02345 if (!last && !found->next) { 02346 /* resource was found to be unique, 02347 leave loop */ 02348 break; 02349 } 02350 /* search for resource in our list 02351 and take it out for the moment */ 02352 if (last) { 02353 last->next = found->next; 02354 } else { 02355 buddy->resources = found->next; 02356 } 02357 02358 last = NULL; 02359 tmp = buddy->resources; 02360 if (!buddy->resources) { 02361 buddy->resources = found; 02362 } 02363 /* priority processing */ 02364 while (tmp) { 02365 /* insert resource back according to 02366 its priority value */ 02367 if (found->priority > tmp->priority) { 02368 if (last) { 02369 /* insert within list */ 02370 last->next = found; 02371 } 02372 found->next = tmp; 02373 if (!last) { 02374 /* insert on top */ 02375 buddy->resources = found; 02376 } 02377 break; 02378 } 02379 if (!tmp->next) { 02380 /* insert at the end of the list */ 02381 tmp->next = found; 02382 found->next = NULL; 02383 break; 02384 } 02385 last = tmp; 02386 tmp = tmp->next; 02387 } 02388 } 02389 break; 02390 } 02391 last = tmp; 02392 tmp = tmp->next; 02393 } 02394 02395 /* resource not found in our list, create it */ 02396 if (!found && status != 6 && pak->from->resource) { 02397 found = ast_calloc(1, sizeof(*found)); 02398 02399 if (!found) { 02400 ast_log(LOG_ERROR, "Out of memory!\n"); 02401 ASTOBJ_UNLOCK(buddy); 02402 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02403 return; 02404 } 02405 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02406 found->status = status; 02407 found->description = descrip; 02408 found->priority = priority; 02409 found->next = NULL; 02410 last = NULL; 02411 tmp = buddy->resources; 02412 while (tmp) { 02413 if (found->priority > tmp->priority) { 02414 if (last) { 02415 last->next = found; 02416 } 02417 found->next = tmp; 02418 if (!last) { 02419 buddy->resources = found; 02420 } 02421 break; 02422 } 02423 if (!tmp->next) { 02424 tmp->next = found; 02425 break; 02426 } 02427 last = tmp; 02428 tmp = tmp->next; 02429 } 02430 if (!tmp) { 02431 buddy->resources = found; 02432 } 02433 } 02434 02435 ASTOBJ_UNLOCK(buddy); 02436 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02437 02438 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02439 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02440 02441 /* handle gmail client's special caps:c tag */ 02442 if (!node && !ver) { 02443 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02444 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02445 } 02446 02447 /* retrieve capabilites of the new resource */ 02448 if (status != 6 && found && !found->cap) { 02449 found->cap = aji_find_version(node, ver, pak); 02450 if (gtalk_yuck(pak->x)) { /* gtalk should do discover */ 02451 found->cap->jingle = 1; 02452 } 02453 if (found->cap->jingle) { 02454 ast_debug(1, "Special case for google till they support discover.\n"); 02455 } else { 02456 iks *iq, *query; 02457 iq = iks_new("iq"); 02458 query = iks_new("query"); 02459 if (query && iq) { 02460 iks_insert_attrib(iq, "type", "get"); 02461 iks_insert_attrib(iq, "to", pak->from->full); 02462 iks_insert_attrib(iq, "from", client->jid->full); 02463 iks_insert_attrib(iq, "id", client->mid); 02464 ast_aji_increment_mid(client->mid); 02465 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02466 iks_insert_node(iq, query); 02467 ast_aji_send(client, iq); 02468 } else { 02469 ast_log(LOG_ERROR, "Out of memory.\n"); 02470 } 02471 iks_delete(query); 02472 iks_delete(iq); 02473 } 02474 } 02475 switch (pak->subtype) { 02476 case IKS_TYPE_AVAILABLE: 02477 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 02478 break; 02479 case IKS_TYPE_UNAVAILABLE: 02480 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 02481 break; 02482 default: 02483 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 02484 } 02485 switch (pak->show) { 02486 case IKS_SHOW_UNAVAILABLE: 02487 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02488 break; 02489 case IKS_SHOW_AVAILABLE: 02490 ast_debug(3, "JABBER: type is available\n"); 02491 break; 02492 case IKS_SHOW_CHAT: 02493 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02494 break; 02495 case IKS_SHOW_AWAY: 02496 ast_debug(3, "JABBER: type is away\n"); 02497 break; 02498 case IKS_SHOW_XA: 02499 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02500 break; 02501 case IKS_SHOW_DND: 02502 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02503 break; 02504 default: 02505 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 02506 } 02507 02508 if (found) { 02509 manager_event(EVENT_FLAG_USER, "JabberStatus", 02510 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 02511 "\r\nDescription: %s\r\n", 02512 client->name, pak->from->partial, found->resource, found->status, 02513 found->priority, S_OR(found->description, "")); 02514 } else { 02515 manager_event(EVENT_FLAG_USER, "JabberStatus", 02516 "Account: %s\r\nJID: %s\r\nStatus: %d\r\n", 02517 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE); 02518 } 02519 }
| static int aji_handle_pubsub_error | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 3502 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_debug, ast_log(), ast_test_flag, ASTOBJ_REF, ASTOBJ_UNREF, and LOG_ERROR.
Referenced by aji_init_event_distribution().
03503 { 03504 char *node_name; 03505 char *error; 03506 int error_num; 03507 iks *orig_request; 03508 iks *orig_pubsub = iks_find(pak->x, "pubsub"); 03509 struct aji_client *client; 03510 if (!orig_pubsub) { 03511 ast_debug(1, "Error isn't a PubSub error, why are we here?\n"); 03512 return IKS_FILTER_EAT; 03513 } 03514 orig_request = iks_child(orig_pubsub); 03515 error = iks_find_attrib(iks_find(pak->x, "error"), "code"); 03516 node_name = iks_find_attrib(orig_request, "node"); 03517 if (!sscanf(error, "%30d", &error_num)) { 03518 return IKS_FILTER_EAT; 03519 } 03520 if (error_num > 399 && error_num < 500 && error_num != 404) { 03521 ast_log(LOG_ERROR, 03522 "Error performing operation on PubSub node %s, %s.\n", node_name, error); 03523 return IKS_FILTER_EAT; 03524 } else if (error_num > 499 && error_num < 600) { 03525 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error); 03526 return IKS_FILTER_EAT; 03527 } 03528 03529 client = ASTOBJ_REF((struct aji_client *) data); 03530 03531 if (!strcasecmp(iks_name(orig_request), "publish")) { 03532 iks *request; 03533 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03534 if (iks_find(iks_find(orig_request, "item"), "state")) { 03535 aji_create_pubsub_leaf(client, "device_state", node_name); 03536 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) { 03537 aji_create_pubsub_leaf(client, "message_waiting", node_name); 03538 } 03539 } else { 03540 aji_create_pubsub_node(client, NULL, node_name, NULL); 03541 } 03542 request = aji_pubsub_iq_create(client, "set"); 03543 iks_insert_node(request, orig_pubsub); 03544 ast_aji_send(client, request); 03545 iks_delete(request); 03546 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03547 return IKS_FILTER_EAT; 03548 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) { 03549 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03550 aji_create_pubsub_collection(client, node_name); 03551 } else { 03552 aji_create_pubsub_node(client, NULL, node_name, NULL); 03553 } 03554 } 03555 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03556 return IKS_FILTER_EAT; 03557 }
| 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 3261 of file res_jabber.c.
References AST_DEVSTATE_CACHABLE, ast_devstate_val(), ast_eid_cmp(), ast_eid_default, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CACHABLE, 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(), ast_event_queue_and_cache(), ast_log(), ast_str_to_eid(), LOG_DEBUG, LOG_ERROR, and mailbox.
Referenced by aji_init_event_distribution().
03262 { 03263 char *item_id, *device_state, *mailbox, *cachable_str; 03264 int oldmsgs, newmsgs; 03265 iks *item, *item_content; 03266 struct ast_eid pubsub_eid; 03267 struct ast_event *event; 03268 unsigned int cachable = AST_DEVSTATE_CACHABLE; 03269 03270 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); 03271 if (!item) { 03272 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); 03273 return IKS_FILTER_EAT; 03274 } 03275 item_id = iks_find_attrib(item, "id"); 03276 item_content = iks_child(item); 03277 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid")); 03278 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) { 03279 ast_log(LOG_DEBUG, "Returning here, eid of incoming event matches ours!\n"); 03280 return IKS_FILTER_EAT; 03281 } 03282 if (!strcasecmp(iks_name(item_content), "state")) { 03283 if ((cachable_str = iks_find_attrib(item_content, "cachable"))) { 03284 sscanf(cachable_str, "%30d", &cachable); 03285 } 03286 device_state = iks_find_cdata(item, "state"); 03287 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, 03288 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, 03289 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, 03290 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03291 AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable, 03292 AST_EVENT_IE_END))) { 03293 return IKS_FILTER_EAT; 03294 } 03295 } else if (!strcasecmp(iks_name(item_content), "mailbox")) { 03296 mailbox = strsep(&item_id, "@"); 03297 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs); 03298 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs); 03299 if (!(event = ast_event_new(AST_EVENT_MWI, 03300 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03301 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, item_id, 03302 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, oldmsgs, 03303 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, newmsgs, 03304 AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03305 AST_EVENT_IE_END))) { 03306 return IKS_FILTER_EAT; 03307 } 03308 } else { 03309 ast_log(LOG_DEBUG, "Don't know how to handle PubSub event of type %s\n", 03310 iks_name(item_content)); 03311 return IKS_FILTER_EAT; 03312 } 03313 03314 if (cachable == AST_DEVSTATE_CACHABLE) { 03315 ast_event_queue_and_cache(event); 03316 } else { 03317 ast_event_queue(event); 03318 } 03319 03320 return IKS_FILTER_EAT; 03321 }
| static void aji_handle_subscribe | ( | struct aji_client * | client, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 2528 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_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, aji_client::component, aji_client::flags, aji_client::jid, LOG_ERROR, option_verbose, aji_client::status, status, aji_client::statusmessage, and VERBOSE_PREFIX_3.
Referenced by aji_act_hook().
02529 { 02530 iks *presence = NULL, *status = NULL; 02531 struct aji_buddy* buddy = NULL; 02532 02533 switch (pak->subtype) { 02534 case IKS_TYPE_SUBSCRIBE: 02535 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) { 02536 presence = iks_new("presence"); 02537 status = iks_new("status"); 02538 if (presence && status) { 02539 iks_insert_attrib(presence, "type", "subscribed"); 02540 iks_insert_attrib(presence, "to", pak->from->full); 02541 iks_insert_attrib(presence, "from", client->jid->full); 02542 if (pak->id) 02543 iks_insert_attrib(presence, "id", pak->id); 02544 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02545 iks_insert_node(presence, status); 02546 ast_aji_send(client, presence); 02547 } else { 02548 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02549 } 02550 02551 iks_delete(presence); 02552 iks_delete(status); 02553 } 02554 02555 if (client->component) 02556 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02557 case IKS_TYPE_SUBSCRIBED: 02558 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02559 if (!buddy && pak->from->partial) { 02560 aji_create_buddy(pak->from->partial, client); 02561 } else if (buddy) { 02562 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02563 } 02564 default: 02565 if (option_verbose > 4) { 02566 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 02567 } 02568 } 02569 }
| 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 3232 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().
03233 { 03234 if (!mwi_sub) { 03235 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription", 03236 client, AST_EVENT_IE_END); 03237 } 03238 if (!device_state_sub) { 03239 if (ast_enable_distributed_devstate()) { 03240 return; 03241 } 03242 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 03243 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END); 03244 ast_event_dump_cache(device_state_sub); 03245 } 03246 03247 aji_pubsub_subscribe(client, "device_state"); 03248 aji_pubsub_subscribe(client, "message_waiting"); 03249 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE, 03250 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE); 03251 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE, 03252 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE); 03253 03254 }
| static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 3122 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, aji_client::stream_flags, and aji_client::user.
Referenced by aji_reconnect().
03123 { 03124 int connected = IKS_NET_NOCONN; 03125 03126 #ifdef HAVE_OPENSSL 03127 /* reset stream flags */ 03128 client->stream_flags = 0; 03129 #endif 03130 /* If it's a component, connect to user, otherwise, connect to server */ 03131 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 03132 03133 if (connected == IKS_NET_NOCONN) { 03134 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 03135 return IKS_HOOK; 03136 } else if (connected == IKS_NET_NODNS) { 03137 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, 03138 S_OR(client->serverhost, client->jid->server)); 03139 return IKS_HOOK; 03140 } 03141 03142 return IKS_OK; 03143 }
| static int aji_io_recv | ( | struct aji_client * | client, | |
| char * | buffer, | |||
| size_t | buf_len, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 1293 of file res_jabber.c.
References aji_is_secure(), ast_poll, len(), aji_client::p, and aji_client::ssl_session.
Referenced by aji_recv().
01294 { 01295 struct pollfd pfd = { .events = POLLIN }; 01296 int len, res; 01297 01298 #ifdef HAVE_OPENSSL 01299 if (aji_is_secure(client)) { 01300 pfd.fd = SSL_get_fd(client->ssl_session); 01301 if (pfd.fd < 0) { 01302 return -1; 01303 } 01304 } else 01305 #endif /* HAVE_OPENSSL */ 01306 pfd.fd = iks_fd(client->p); 01307 01308 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1); 01309 if (res > 0) { 01310 #ifdef HAVE_OPENSSL 01311 if (aji_is_secure(client)) { 01312 len = SSL_read(client->ssl_session, buffer, buf_len); 01313 } else 01314 #endif /* HAVE_OPENSSL */ 01315 len = recv(pfd.fd, buffer, buf_len, 0); 01316 01317 if (len > 0) { 01318 return len; 01319 } else if (len <= 0) { 01320 return -1; 01321 } 01322 } 01323 return res; 01324 }
| static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Definition at line 1203 of file res_jabber.c.
References SECURE, and aji_client::stream_flags.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
01204 { 01205 #ifdef HAVE_OPENSSL 01206 return client->stream_flags & SECURE; 01207 #else 01208 return 0; 01209 #endif 01210 }
| 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 988 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().
00989 { 00990 struct aji_client *client = NULL; 00991 char *s; 00992 char nick[AJI_MAX_RESJIDLEN]; 00993 00994 AST_DECLARE_APP_ARGS(args, 00995 AST_APP_ARG(sender); 00996 AST_APP_ARG(jid); 00997 AST_APP_ARG(nick); 00998 ); 00999 01000 if (!data) { 01001 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01002 return -1; 01003 } 01004 s = ast_strdupa(data); 01005 01006 AST_STANDARD_APP_ARGS(args, s); 01007 if (args.argc < 2 || args.argc > 3) { 01008 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01009 return -1; 01010 } 01011 01012 if (strchr(args.jid, '/')) { 01013 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n"); 01014 return -1; 01015 } 01016 01017 if (!(client = ast_aji_get_client(args.sender))) { 01018 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01019 return -1; 01020 } 01021 01022 if (!ast_strlen_zero(args.nick)) { 01023 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01024 } else { 01025 if (client->component) { 01026 sprintf(nick, "asterisk"); 01027 } else { 01028 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01029 } 01030 } 01031 01032 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01033 ast_aji_join_chat(client, args.jid, nick); 01034 } else { 01035 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid); 01036 } 01037 01038 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01039 return 0; 01040 }
| 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 1049 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().
01050 { 01051 struct aji_client *client = NULL; 01052 char *s; 01053 char nick[AJI_MAX_RESJIDLEN]; 01054 AST_DECLARE_APP_ARGS(args, 01055 AST_APP_ARG(sender); 01056 AST_APP_ARG(jid); 01057 AST_APP_ARG(nick); 01058 ); 01059 01060 if (!data) { 01061 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01062 return -1; 01063 } 01064 s = ast_strdupa(data); 01065 01066 AST_STANDARD_APP_ARGS(args, s); 01067 if (args.argc < 2 || args.argc > 3) { 01068 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01069 return -1; 01070 } 01071 01072 if (strchr(args.jid, '/')) { 01073 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n"); 01074 return -1; 01075 } 01076 01077 if (!(client = ast_aji_get_client(args.sender))) { 01078 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01079 return -1; 01080 } 01081 01082 if (!ast_strlen_zero(args.nick)) { 01083 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01084 } else { 01085 if (client->component) { 01086 sprintf(nick, "asterisk"); 01087 } else { 01088 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01089 } 01090 } 01091 01092 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01093 ast_aji_leave_chat(client, args.jid, nick); 01094 } 01095 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01096 return 0; 01097 }
| static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 4514 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, JABBER_CONFIG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by aji_reload().
04515 { 04516 char *cat = NULL; 04517 int debug = 0; 04518 struct ast_config *cfg = NULL; 04519 struct ast_variable *var = NULL; 04520 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04521 04522 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 04523 return -1; 04524 } 04525 04526 /* Reset flags to default value */ 04527 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT); 04528 04529 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 04530 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 04531 return 0; 04532 } 04533 04534 cat = ast_category_browse(cfg, NULL); 04535 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 04536 if (!strcasecmp(var->name, "debug")) { 04537 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 04538 } else if (!strcasecmp(var->name, "autoprune")) { 04539 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 04540 } else if (!strcasecmp(var->name, "autoregister")) { 04541 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 04542 } else if (!strcasecmp(var->name, "collection_nodes")) { 04543 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248); 04544 } else if (!strcasecmp(var->name, "pubsub_autocreate")) { 04545 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE); 04546 } else if (!strcasecmp(var->name, "auth_policy")) { 04547 if (!strcasecmp(var->value, "accept")) { 04548 ast_set_flag(&globalflags, AJI_AUTOACCEPT); 04549 } else { 04550 ast_clear_flag(&globalflags, AJI_AUTOACCEPT); 04551 } 04552 } 04553 } 04554 04555 while (cat) { 04556 if (strcasecmp(cat, "general")) { 04557 var = ast_variable_browse(cfg, cat); 04558 aji_create_client(cat, var, debug); 04559 } 04560 cat = ast_category_browse(cfg, cat); 04561 } 04562 ast_config_destroy(cfg); /* or leak memory */ 04563 return 1; 04564 }
| static void aji_log_hook | ( | void * | data, | |
| const char * | xmpp, | |||
| size_t | size, | |||
| int | is_incoming | |||
| ) | [static] |
Definition at line 1484 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().
01485 { 01486 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01487 01488 if (!ast_strlen_zero(xmpp)) { 01489 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 01490 } 01491 01492 if (client->debug) { 01493 if (is_incoming) { 01494 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 01495 } else { 01496 if (strlen(xmpp) == 1) { 01497 if (option_debug > 2 && xmpp[0] == ' ') { 01498 ast_verbose("\nJABBER: Keep alive packet\n"); 01499 } 01500 } else { 01501 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 01502 } 01503 } 01504 01505 } 01506 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01507 }
| static void aji_message_destroy | ( | struct aji_message * | obj | ) | [static] |
Definition at line 451 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().
| 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 3175 of file res_jabber.c.
References aji_publish_mwi(), ast_aji_client_destroy(), 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, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, context, LOG_DEBUG, and mailbox.
Referenced by aji_init_event_distribution().
03176 { 03177 const char *mailbox; 03178 const char *context; 03179 char oldmsgs[10]; 03180 char newmsgs[10]; 03181 struct aji_client *client; 03182 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03183 { 03184 /* If the event didn't originate from this server, don't send it back out. */ 03185 ast_log(LOG_DEBUG, "Returning here\n"); 03186 return; 03187 } 03188 03189 client = ASTOBJ_REF((struct aji_client *) data); 03190 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX); 03191 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT); 03192 snprintf(oldmsgs, sizeof(oldmsgs), "%d", 03193 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS)); 03194 snprintf(newmsgs, sizeof(newmsgs), "%d", 03195 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS)); 03196 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs); 03197 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03198 03199 }
| static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2896 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.
02897 { 02898 iks *removeiq = iks_new("iq"); 02899 iks *removequery = iks_new("query"); 02900 iks *removeitem = iks_new("item"); 02901 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02902 if (!client || !removeiq || !removequery || !removeitem || !send) { 02903 ast_log(LOG_ERROR, "Out of memory.\n"); 02904 goto safeout; 02905 } 02906 02907 iks_insert_node(removeiq, removequery); 02908 iks_insert_node(removequery, removeitem); 02909 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02910 ASTOBJ_RDLOCK(iterator); 02911 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02912 * be called at the same time */ 02913 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02914 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02915 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02916 " so I am no longer subscribing to your presence.\n")); 02917 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02918 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02919 " your access to my presence.\n")); 02920 iks_insert_attrib(removeiq, "from", client->jid->full); 02921 iks_insert_attrib(removeiq, "type", "set"); 02922 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02923 iks_insert_attrib(removeitem, "jid", iterator->name); 02924 iks_insert_attrib(removeitem, "subscription", "remove"); 02925 ast_aji_send(client, removeiq); 02926 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02927 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02928 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02929 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02930 } 02931 ASTOBJ_UNLOCK(iterator); 02932 }); 02933 02934 safeout: 02935 iks_delete(removeiq); 02936 iks_delete(removequery); 02937 iks_delete(removeitem); 02938 iks_delete(send); 02939 02940 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, ast_aji_buddy_destroy); 02941 }
| static void aji_publish_device_state | ( | struct aji_client * | client, | |
| const char * | device, | |||
| const char * | device_state, | |||
| unsigned int | cachable | |||
| ) | [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 3435 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().
03437 { 03438 iks *request = aji_build_publish_skeleton(client, device, "device_state", cachable); 03439 iks *state; 03440 char eid_str[20], cachable_str[2]; 03441 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { 03442 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03443 aji_create_pubsub_node(client, "leaf", device, "device_state"); 03444 } else { 03445 aji_create_pubsub_node(client, NULL, device, NULL); 03446 } 03447 } 03448 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03449 state = iks_insert(request, "state"); 03450 iks_insert_attrib(state, "xmlns", "http://asterisk.org"); 03451 iks_insert_attrib(state, "eid", eid_str); 03452 snprintf(cachable_str, sizeof(cachable_str), "%u", cachable); 03453 iks_insert_attrib(state, "cachable", cachable_str); 03454 iks_insert_cdata(state, device_state, strlen(device_state)); 03455 ast_aji_send(client, iks_root(request)); 03456 iks_delete(request); 03457 }
| 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 3466 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().
03468 { 03469 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT]; 03470 char eid_str[20]; 03471 iks *mailbox_node, *request; 03472 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); 03473 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting", 1); 03474 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03475 mailbox_node = iks_insert(request, "mailbox"); 03476 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org"); 03477 iks_insert_attrib(mailbox_node, "eid", eid_str); 03478 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs)); 03479 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs)); 03480 ast_aji_send(client, iks_root(request)); 03481 iks_delete(request); 03482 }
| 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 3490 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().
03491 { 03492 iks *request = iks_new("iq"); 03493 03494 iks_insert_attrib(request, "to", client->pubsub_node); 03495 iks_insert_attrib(request, "from", client->jid->full); 03496 iks_insert_attrib(request, "type", type); 03497 ast_aji_increment_mid(client->mid); 03498 iks_insert_attrib(request, "id", client->mid); 03499 return request; 03500 }
| static void aji_pubsub_purge_nodes | ( | struct aji_client * | client, | |
| const char * | collection_name | |||
| ) | [static] |
Definition at line 3710 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().
03711 { 03712 iks *request = aji_build_node_request(client, collection_name); 03713 ast_aji_send(client, request); 03714 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE, 03715 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03716 IKS_RULE_DONE); 03717 ast_aji_send(client, request); 03718 iks_delete(request); 03719 }
| 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 3354 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_send(), ast_test_flag, and aji_client::jid.
Referenced by aji_init_event_distribution().
03355 { 03356 iks *request = aji_pubsub_iq_create(client, "set"); 03357 iks *pubsub, *subscribe; 03358 03359 pubsub = iks_insert(request, "pubsub"); 03360 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03361 subscribe = iks_insert(pubsub, "subscribe"); 03362 iks_insert_attrib(subscribe, "jid", client->jid->partial); 03363 iks_insert_attrib(subscribe, "node", node); 03364 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03365 iks *options, *x, *sub_options, *sub_type, *sub_depth; 03366 options = iks_insert(pubsub, "options"); 03367 x = iks_insert(options, "x"); 03368 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03369 iks_insert_attrib(x, "type", "submit"); 03370 sub_options = iks_insert(x, "field"); 03371 iks_insert_attrib(sub_options, "var", "FORM_TYPE"); 03372 iks_insert_attrib(sub_options, "type", "hidden"); 03373 iks_insert_cdata(iks_insert(sub_options, "value"), 03374 "http://jabber.org/protocol/pubsub#subscribe_options", 51); 03375 sub_type = iks_insert(x, "field"); 03376 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type"); 03377 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5); 03378 sub_depth = iks_insert(x, "field"); 03379 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth"); 03380 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3); 03381 } 03382 ast_aji_send(client, request); 03383 iks_delete(request); 03384 }
| 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 3601 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().
03602 { 03603 03604 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03605 iks *item = NULL; 03606 if (iks_has_children(pak->query)) { 03607 item = iks_first_tag(pak->query); 03608 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial, 03609 iks_find_attrib(item, "node")); 03610 while ((item = iks_next_tag(item))) { 03611 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node")); 03612 } 03613 } 03614 if (item) { 03615 iks_delete(item); 03616 } 03617 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03618 return IKS_FILTER_EAT; 03619 }
| static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 3038 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().
03039 { 03040 int res = 0; 03041 03042 if (client->state) { 03043 client->state = AJI_DISCONNECTED; 03044 } 03045 client->timeout = 50; 03046 if (client->p) { 03047 iks_parser_reset(client->p); 03048 } 03049 if (client->authorized) { 03050 client->authorized = 0; 03051 } 03052 03053 res = aji_initialize(client); 03054 03055 return res; 03056 }
| static int aji_recv | ( | struct aji_client * | client, | |
| int | timeout | |||
| ) | [static] |
Definition at line 1338 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().
01339 { 01340 int len, ret; 01341 char buf[NET_IO_BUF_SIZE - 1]; 01342 char newbuf[NET_IO_BUF_SIZE - 1]; 01343 int pos = 0; 01344 int newbufpos = 0; 01345 unsigned char c; 01346 01347 memset(buf, 0, sizeof(buf)); 01348 memset(newbuf, 0, sizeof(newbuf)); 01349 01350 while (1) { 01351 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 01352 if (len < 0) return IKS_NET_RWERR; 01353 if (len == 0) return IKS_NET_EXPIRED; 01354 buf[len] = '\0'; 01355 01356 /* our iksemel parser won't work as expected if we feed 01357 it with XML packets that contain multiple whitespace 01358 characters between tags */ 01359 while (pos < len) { 01360 c = buf[pos]; 01361 /* if we stumble on the ending tag character, 01362 we skip any whitespace that follows it*/ 01363 if (c == '>') { 01364 while (isspace(buf[pos+1])) { 01365 pos++; 01366 } 01367 } 01368 newbuf[newbufpos] = c; 01369 newbufpos ++; 01370 pos++; 01371 } 01372 pos = 0; 01373 newbufpos = 0; 01374 01375 /* Log the message here, because iksemel's logHook is 01376 unaccessible */ 01377 aji_log_hook(client, buf, len, 1); 01378 01379 /* let iksemel deal with the string length, 01380 and reset our buffer */ 01381 ret = iks_parse(client->p, newbuf, 0, 0); 01382 memset(newbuf, 0, sizeof(newbuf)); 01383 01384 switch (ret) { 01385 case IKS_NOMEM: 01386 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 01387 break; 01388 case IKS_BADXML: 01389 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 01390 break; 01391 case IKS_HOOK: 01392 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 01393 break; 01394 } 01395 if (ret != IKS_OK) { 01396 return ret; 01397 } 01398 ast_debug(3, "XML parsing successful\n"); 01399 } 01400 return IKS_OK; 01401 }
| static void * aji_recv_loop | ( | void * | data | ) | [static] |
Definition at line 2730 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().
02731 { 02732 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02733 int res = IKS_HOOK; 02734 02735 while (res != IKS_OK) { 02736 ast_debug(3, "JABBER: Connecting.\n"); 02737 res = aji_reconnect(client); 02738 sleep(4); 02739 } 02740 02741 do { 02742 if (res == IKS_NET_RWERR || client->timeout == 0) { 02743 while (res != IKS_OK) { 02744 ast_debug(3, "JABBER: reconnecting.\n"); 02745 res = aji_reconnect(client); 02746 sleep(4); 02747 } 02748 } 02749 02750 res = aji_recv(client, 1); 02751 02752 if (client->state == AJI_DISCONNECTING) { 02753 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02754 pthread_exit(NULL); 02755 } 02756 02757 /* Decrease timeout if no data received, and delete 02758 * old messages globally */ 02759 if (res == IKS_NET_EXPIRED) { 02760 client->timeout--; 02761 delete_old_messages_all(client); 02762 } 02763 if (res == IKS_HOOK) { 02764 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02765 } else if (res == IKS_NET_TLSFAIL) { 02766 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02767 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02768 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02769 if (res == IKS_OK) { 02770 client->timeout = 50; 02771 } else { 02772 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02773 } 02774 } else if (res == IKS_NET_RWERR) { 02775 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02776 } 02777 } while (client); 02778 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02779 return 0; 02780 }
| static int aji_register_approve_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1787 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().
01788 { 01789 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01790 iks *iq = NULL, *presence = NULL, *x = NULL; 01791 01792 iq = iks_new("iq"); 01793 presence = iks_new("presence"); 01794 x = iks_new("x"); 01795 if (client && iq && presence && x) { 01796 if (!iks_find(pak->query, "remove")) { 01797 iks_insert_attrib(iq, "from", client->jid->full); 01798 iks_insert_attrib(iq, "to", pak->from->full); 01799 iks_insert_attrib(iq, "id", pak->id); 01800 iks_insert_attrib(iq, "type", "result"); 01801 ast_aji_send(client, iq); 01802 01803 iks_insert_attrib(presence, "from", client->jid->full); 01804 iks_insert_attrib(presence, "to", pak->from->partial); 01805 iks_insert_attrib(presence, "id", client->mid); 01806 ast_aji_increment_mid(client->mid); 01807 iks_insert_attrib(presence, "type", "subscribe"); 01808 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01809 iks_insert_node(presence, x); 01810 ast_aji_send(client, presence); 01811 } 01812 } else { 01813 ast_log(LOG_ERROR, "Out of memory.\n"); 01814 } 01815 01816 iks_delete(iq); 01817 iks_delete(presence); 01818 iks_delete(x); 01819 01820 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01821 return IKS_FILTER_EAT; 01822 }
| static int aji_register_query_handler | ( | void * | data, | |
| ikspak * | pak | |||
| ) | [static] |
Definition at line 1830 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().
01831 { 01832 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01833 struct aji_buddy *buddy = NULL; 01834 char *node = NULL; 01835 iks *iq = NULL, *query = NULL; 01836 01837 client = (struct aji_client *) data; 01838 01839 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01840 if (!buddy) { 01841 iks *error = NULL, *notacceptable = NULL; 01842 01843 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01844 iq = iks_new("iq"); 01845 query = iks_new("query"); 01846 error = iks_new("error"); 01847 notacceptable = iks_new("not-acceptable"); 01848 if (iq && query && error && notacceptable) { 01849 iks_insert_attrib(iq, "type", "error"); 01850 iks_insert_attrib(iq, "from", client->user); 01851 iks_insert_attrib(iq, "to", pak->from->full); 01852 iks_insert_attrib(iq, "id", pak->id); 01853 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01854 iks_insert_attrib(error, "code" , "406"); 01855 iks_insert_attrib(error, "type", "modify"); 01856 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01857 iks_insert_node(iq, query); 01858 iks_insert_node(iq, error); 01859 iks_insert_node(error, notacceptable); 01860 ast_aji_send(client, iq); 01861 } else { 01862 ast_log(LOG_ERROR, "Out of memory.\n"); 01863 } 01864 01865 iks_delete(error); 01866 iks_delete(notacceptable); 01867 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01868 iks *instructions = NULL; 01869 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01870 iq = iks_new("iq"); 01871 query = iks_new("query"); 01872 instructions = iks_new("instructions"); 01873 if (iq && query && instructions && client) { 01874 iks_insert_attrib(iq, "from", client->user); 01875 iks_insert_attrib(iq, "to", pak->from->full); 01876 iks_insert_attrib(iq, "id", pak->id); 01877 iks_insert_attrib(iq, "type", "result"); 01878 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01879 iks_insert_cdata(instructions, explain, 0); 01880 iks_insert_node(iq, query); 01881 iks_insert_node(query, instructions); 01882 ast_aji_send(client, iq); 01883 } else { 01884 ast_log(LOG_ERROR, "Out of memory.\n"); 01885 } 01886 01887 iks_delete(instructions); 01888 } 01889 iks_delete(iq); 01890 iks_delete(query); 01891 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 01892 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01893 return IKS_FILTER_EAT; 01894 }
| static int aji_reload | ( | int | reload | ) | [static] |
Definition at line 4651 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().
04652 { 04653 int res; 04654 04655 ASTOBJ_CONTAINER_MARKALL(&clients); 04656 if (!(res = aji_load_config(reload))) { 04657 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 04658 return 0; 04659 } else if (res == -1) 04660 return 1; 04661 04662 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, ast_aji_client_destroy); 04663 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04664 ASTOBJ_RDLOCK(iterator); 04665 if (iterator->state == AJI_DISCONNECTED) { 04666 if (!iterator->thread) 04667 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 04668 } else if (iterator->state == AJI_CONNECTING) { 04669 aji_get_roster(iterator); 04670 if (iterator->distribute_events) { 04671 aji_init_event_distribution(iterator); 04672 } 04673 } 04674 04675 ASTOBJ_UNLOCK(iterator); 04676 }); 04677 04678 return 1; 04679 }
| 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 3565 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().
03566 { 03567 iks *request = aji_build_node_request(client, collection); 03568 03569 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE, 03570 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03571 IKS_RULE_DONE); 03572 ast_aji_send(client, request); 03573 iks_delete(request); 03574 03575 }
| static int aji_send_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 1107 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().
01108 { 01109 struct aji_client *client = NULL; 01110 char *s; 01111 AST_DECLARE_APP_ARGS(args, 01112 AST_APP_ARG(sender); 01113 AST_APP_ARG(recipient); 01114 AST_APP_ARG(message); 01115 ); 01116 01117 if (!data) { 01118 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01119 return -1; 01120 } 01121 s = ast_strdupa(data); 01122 01123 AST_STANDARD_APP_ARGS(args, s); 01124 if (args.argc < 3) { 01125 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01126 return -1; 01127 } 01128 01129 if (!(client = ast_aji_get_client(args.sender))) { 01130 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 01131 return -1; 01132 } 01133 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) { 01134 ast_aji_send_chat(client, args.recipient, args.message); 01135 } 01136 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01137 return 0; 01138 }
| static int aji_send_header | ( | struct aji_client * | client, | |
| const char * | to | |||
| ) | [static] |
Definition at line 1410 of file res_jabber.c.
References aji_send_raw(), len(), and aji_client::name_space.
Referenced by aji_act_hook(), and aji_tls_handshake().
01411 { 01412 char *msg; 01413 int len, err; 01414 01415 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 01416 msg = iks_malloc(len); 01417 if (!msg) 01418 return IKS_NOMEM; 01419 sprintf(msg, "<?xml version='1.0'?>" 01420 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 01421 "%s' to='%s' version='1.0'>", client->name_space, to); 01422 err = aji_send_raw(client, msg); 01423 iks_free(msg); 01424 if (err != IKS_OK) 01425 return err; 01426 01427 return IKS_OK; 01428 }
| static int aji_send_raw | ( | struct aji_client * | client, | |
| const char * | xmlstr | |||
| ) | [static] |
Definition at line 1450 of file res_jabber.c.
References aji_is_secure(), aji_log_hook(), len(), aji_client::p, and aji_client::ssl_session.
Referenced by aji_act_hook(), aji_recv_loop(), aji_send_header(), and ast_aji_send().
01451 { 01452 int ret; 01453 #ifdef HAVE_OPENSSL 01454 int len = strlen(xmlstr); 01455 01456 if (aji_is_secure(client)) { 01457 ret = SSL_write(client->ssl_session, xmlstr, len); 01458 if (ret) { 01459 /* Log the message here, because iksemel's logHook is 01460 unaccessible */ 01461 aji_log_hook(client, xmlstr, len, 0); 01462 return IKS_OK; 01463 } 01464 } 01465 #endif 01466 /* If needed, data will be sent unencrypted, and logHook will 01467 be called inside iks_send_raw */ 01468 ret = iks_send_raw(client->p, xmlstr); 01469 if (ret != IKS_OK) { 01470 return ret; 01471 } 01472 01473 return IKS_OK; 01474 }
| 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 2606 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().
02607 { 02608 int res = 0; 02609 iks *message_packet = NULL; 02610 char from[AJI_MAX_JIDLEN]; 02611 /* the nickname is used only in component mode */ 02612 if (nick && client->component) { 02613 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 02614 } else { 02615 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 02616 } 02617 02618 if (client->state != AJI_CONNECTED) { 02619 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02620 return -1; 02621 } 02622 02623 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message); 02624 if (!message_packet) { 02625 ast_log(LOG_ERROR, "Out of memory.\n"); 02626 return -1; 02627 } 02628 iks_insert_attrib(message_packet, "from", from); 02629 res = ast_aji_send(client, message_packet); 02630 iks_delete(message_packet); 02631 02632 return res; 02633 }
| 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 1147 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().
01148 { 01149 struct aji_client *client = NULL; 01150 char *s; 01151 char nick[AJI_MAX_RESJIDLEN]; 01152 int res = 0; 01153 AST_DECLARE_APP_ARGS(args, 01154 AST_APP_ARG(sender); 01155 AST_APP_ARG(groupchat); 01156 AST_APP_ARG(message); 01157 AST_APP_ARG(nick); 01158 ); 01159 01160 if (!data) { 01161 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01162 return -1; 01163 } 01164 s = ast_strdupa(data); 01165 01166 AST_STANDARD_APP_ARGS(args, s); 01167 if (args.argc < 3 || args.argc > 4) { 01168 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01169 return -1; 01170 } 01171 01172 if (!(client = ast_aji_get_client(args.sender))) { 01173 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01174 return -1; 01175 } 01176 01177 if (ast_strlen_zero(args.nick) || args.argc == 3) { 01178 if (client->component) { 01179 sprintf(nick, "asterisk"); 01180 } else { 01181 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01182 } 01183 } else { 01184 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01185 } 01186 01187 if (strchr(args.groupchat, '@') && !ast_strlen_zero(args.message)) { 01188 res = ast_aji_send_groupchat(client, nick, args.groupchat, args.message); 01189 } 01190 01191 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01192 if (res != IKS_OK) { 01193 return -1; 01194 } 01195 return 0; 01196 }
| static int aji_set_group_presence | ( | struct aji_client * | client, | |
| char * | room, | |||
| int | level, | |||
| char * | nick, | |||
| char * | desc | |||
| ) | [static] |
Definition at line 4031 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().
04032 { 04033 int res = 0; 04034 iks *presence = NULL, *x = NULL; 04035 char from[AJI_MAX_JIDLEN]; 04036 char roomid[AJI_MAX_JIDLEN]; 04037 04038 presence = iks_make_pres(level, NULL); 04039 x = iks_new("x"); 04040 04041 if (client->component) { 04042 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 04043 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick); 04044 } else { 04045 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 04046 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user); 04047 } 04048 04049 if (!presence || !x || !client) { 04050 ast_log(LOG_ERROR, "Out of memory.\n"); 04051 res = -1; 04052 goto safeout; 04053 } else { 04054 iks_insert_attrib(presence, "to", roomid); 04055 iks_insert_attrib(presence, "from", from); 04056 iks_insert_attrib(x, "xmlns", MUC_NS); 04057 iks_insert_node(presence, x); 04058 res = ast_aji_send(client, presence); 04059 } 04060 04061 safeout: 04062 iks_delete(presence); 04063 iks_delete(x); 04064 return res; 04065 }
| static void aji_set_presence | ( | struct aji_client * | client, | |
| char * | to, | |||
| char * | from, | |||
| int | level, | |||
| char * | desc | |||
| ) | [static] |
Definition at line 3989 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().
03990 { 03991 iks *presence = iks_make_pres(level, desc); 03992 iks *cnode = iks_new("c"); 03993 iks *priority = iks_new("priority"); 03994 char priorityS[10]; 03995 03996 if (presence && cnode && client && priority) { 03997 if (to) { 03998 iks_insert_attrib(presence, "to", to); 03999 } 04000 if (from) { 04001 iks_insert_attrib(presence, "from", from); 04002 } 04003 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 04004 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 04005 iks_insert_node(presence, priority); 04006 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 04007 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 04008 iks_insert_attrib(cnode, "ext", "voice-v1"); 04009 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 04010 iks_insert_node(presence, cnode); 04011 ast_aji_send(client, presence); 04012 } else { 04013 ast_log(LOG_ERROR, "Out of memory.\n"); 04014 } 04015 04016 iks_delete(cnode); 04017 iks_delete(presence); 04018 iks_delete(priority); 04019 }
| static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4183 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.
04184 { 04185 struct aji_resource *resource; 04186 struct aji_client *client; 04187 04188 switch (cmd) { 04189 case CLI_INIT: 04190 e->command = "jabber show buddies"; 04191 e->usage = 04192 "Usage: jabber show buddies\n" 04193 " Shows buddy lists of our clients\n"; 04194 return NULL; 04195 case CLI_GENERATE: 04196 return NULL; 04197 } 04198 04199 ast_cli(a->fd, "Jabber buddy lists\n"); 04200 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04201 ast_cli(a->fd, "Client: %s\n", iterator->user); 04202 client = iterator; 04203 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04204 ASTOBJ_RDLOCK(iterator); 04205 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name); 04206 if (!iterator->resources) 04207 ast_cli(a->fd, "\t\tResource: None\n"); 04208 for (resource = iterator->resources; resource; resource = resource->next) { 04209 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource); 04210 if (resource->cap) { 04211 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node); 04212 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version); 04213 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 04214 } 04215 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status); 04216 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority); 04217 } 04218 ASTOBJ_UNLOCK(iterator); 04219 }); 04220 iterator = client; 04221 }); 04222 return CLI_SUCCESS; 04223 }
| static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 4137 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.
04138 { 04139 char *status; 04140 int count = 0; 04141 04142 switch (cmd) { 04143 case CLI_INIT: 04144 e->command = "jabber show connections"; 04145 e->usage = 04146 "Usage: jabber show connections\n" 04147 " Shows state of client and component connections\n"; 04148 return NULL; 04149 case CLI_GENERATE: 04150 return NULL; 04151 } 04152 04153 ast_cli(a->fd, "Jabber Users and their status:\n"); 04154 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04155 ASTOBJ_RDLOCK(iterator); 04156 count++; 04157 switch (iterator->state) { 04158 case AJI_DISCONNECTED: 04159 status = "Disconnected"; 04160 break; 04161 case AJI_CONNECTING: 04162 status = "Connecting"; 04163 break; 04164 case AJI_CONNECTED: 04165 status = "Connected"; 04166 break; 04167 default: 04168 status = "Unknown"; 04169 } 04170 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status); 04171 ASTOBJ_UNLOCK(iterator); 04172 }); 04173 ast_cli(a->fd, "----\n"); 04174 ast_cli(a->fd, " Number of users: %d\n", count); 04175 return CLI_SUCCESS; 04176 }
| static int aji_start_sasl | ( | struct aji_client * | client, | |
| enum ikssasltype | type, | |||
| char * | username, | |||
| char * | pass | |||
| ) | [static] |
Definition at line 1519 of file res_jabber.c.
References aji_is_secure(), ast_aji_send(), ast_alloca, ast_base64encode(), ast_log(), base64, len(), LOG_ERROR, and aji_client::p.
Referenced by aji_act_hook().
01520 { 01521 iks *x = NULL; 01522 int len; 01523 char *s; 01524 char *base64; 01525 01526 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 01527 iks_start_sasl is an iksemel API function and relies on GnuTLS, 01528 whereas we use OpenSSL */ 01529 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 01530 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 01531 if (!(type & IKS_STREAM_SASL_PLAIN)) { 01532 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 01533 return IKS_NET_NOTSUPP; 01534 } 01535 01536 x = iks_new("auth"); 01537 if (!x) { 01538 ast_log(LOG_ERROR, "Out of memory.\n"); 01539 return IKS_NET_NOTSUPP; 01540 } 01541 01542 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 01543 len = strlen(username) + strlen(pass) + 3; 01544 s = ast_alloca(len); 01545 base64 = ast_alloca((len + 2) * 4 / 3); 01546 iks_insert_attrib(x, "mechanism", "PLAIN"); 01547 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 01548 01549 /* exclude the NULL training byte from the base64 encoding operation 01550 as some XMPP servers will refuse it. 01551 The format for authentication is [authzid]\0authcid\0password 01552 not [authzid]\0authcid\0password\0 */ 01553 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 01554 iks_insert_cdata(x, base64, 0); 01555 ast_aji_send(client, x); 01556 iks_delete(x); 01557 01558 return IKS_OK; 01559 }
| static int aji_start_tls | ( | struct aji_client * | client | ) | [static] |
Definition at line 1220 of file res_jabber.c.
References aji_client::p, aji_client::stream_flags, and TRY_SECURE.
Referenced by aji_act_hook().
01221 { 01222 int ret; 01223 01224 /* This is sent not encrypted */ 01225 if ((ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"))) { 01226 return ret; 01227 } 01228 01229 client->stream_flags |= TRY_SECURE; 01230 return IKS_OK; 01231 }
| static int aji_status_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Definition at line 620 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().
00621 { 00622 struct aji_client *client = NULL; 00623 struct aji_buddy *buddy = NULL; 00624 struct aji_resource *r = NULL; 00625 char *s = NULL; 00626 int stat = 7; 00627 char status[2]; 00628 static int deprecation_warning = 0; 00629 AST_DECLARE_APP_ARGS(args, 00630 AST_APP_ARG(sender); 00631 AST_APP_ARG(jid); 00632 AST_APP_ARG(variable); 00633 ); 00634 AST_DECLARE_APP_ARGS(jid, 00635 AST_APP_ARG(screenname); 00636 AST_APP_ARG(resource); 00637 ); 00638 00639 if (deprecation_warning++ % 10 == 0) { 00640 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00641 } 00642 00643 if (!data) { 00644 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00645 return 0; 00646 } 00647 s = ast_strdupa(data); 00648 AST_STANDARD_APP_ARGS(args, s); 00649 00650 if (args.argc != 3) { 00651 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00652 return -1; 00653 } 00654 00655 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00656 if (jid.argc < 1 || jid.argc > 2) { 00657 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00658 return -1; 00659 } 00660 00661 if (!(client = ast_aji_get_client(args.sender))) { 00662 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00663 return -1; 00664 } 00665 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00666 if (!buddy) { 00667 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00668 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00669 return -1; 00670 } 00671 r = aji_find_resource(buddy, jid.resource); 00672 if (!r && buddy->resources) { 00673 r = buddy->resources; 00674 } 00675 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00676 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00677 if (!r) { 00678 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00679 } else { 00680 stat = r->status; 00681 } 00682 snprintf(status, sizeof(status), "%d", stat); 00683 pbx_builtin_setvar_helper(chan, args.variable, status); 00684 return 0; 00685 }
| static int aji_tls_handshake | ( | struct aji_client * | client | ) | [static] |
Definition at line 1239 of file res_jabber.c.
References aji_send_header(), ast_debug, aji_client::jid, aji_client::p, SECURE, aji_client::ssl_context, aji_client::ssl_method, aji_client::ssl_session, aji_client::stream_flags, and TRY_SECURE.
Referenced by aji_act_hook().
01240 { 01241 int ret; 01242 int sock; 01243 01244 ast_debug(1, "Starting TLS handshake\n"); 01245 01246 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 01247 client->ssl_method = SSLv3_method(); 01248 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) { 01249 return IKS_NET_TLSFAIL; 01250 } 01251 01252 /* Create new SSL session */ 01253 if (!(client->ssl_session = SSL_new(client->ssl_context))) { 01254 return IKS_NET_TLSFAIL; 01255 } 01256 01257 /* Enforce TLS on our XMPP connection */ 01258 sock = iks_fd(client->p); 01259 if (!(ret = SSL_set_fd(client->ssl_session, sock))) { 01260 return IKS_NET_TLSFAIL; 01261 } 01262 01263 /* Perform SSL handshake */ 01264 if (!(ret = SSL_connect(client->ssl_session))) { 01265 return IKS_NET_TLSFAIL; 01266 } 01267 01268 client->stream_flags &= (~TRY_SECURE); 01269 client->stream_flags |= SECURE; 01270 01271 /* Sent over the established TLS connection */ 01272 if ((ret = aji_send_header(client, client->jid->server)) != IKS_OK) { 01273 return IKS_NET_TLSFAIL; 01274 } 01275 01276 ast_debug(1, "TLS started with server\n"); 01277 01278 return IKS_OK; 01279 }
| void ast_aji_buddy_destroy | ( | struct aji_buddy * | obj | ) |
Destructor function for buddies to be used with ASTOBJ_UNREF
Definition at line 432 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(), and jingle_alloc().
00433 { 00434 struct aji_resource *tmp; 00435 00436 while ((tmp = obj->resources)) { 00437 obj->resources = obj->resources->next; 00438 ast_free(tmp->description); 00439 ast_free(tmp); 00440 } 00441 00442 ast_free(obj); 00443 }
| 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 410 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_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_newcall(), gtalk_request(), jingle_load_config(), jingle_newcall(), jingle_request(), manager_jabber_send(), and unload_module().
00411 { 00412 struct aji_message *tmp; 00413 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, ast_aji_buddy_destroy); 00414 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00415 iks_filter_delete(obj->f); 00416 iks_parser_delete(obj->p); 00417 iks_stack_delete(obj->stack); 00418 AST_LIST_LOCK(&obj->messages); 00419 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00420 aji_message_destroy(tmp); 00421 } 00422 AST_LIST_HEAD_DESTROY(&obj->messages); 00423 ast_free(obj); 00424 }
| 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 2643 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02644 { 02645 int res = 0; 02646 iks *iq = NULL; 02647 iq = iks_new("iq"); 02648 02649 if (iq && client) { 02650 iks_insert_attrib(iq, "type", "get"); 02651 iks_insert_attrib(iq, "to", server); 02652 iks_insert_attrib(iq, "id", client->mid); 02653 ast_aji_increment_mid(client->mid); 02654 ast_aji_send(client, iq); 02655 } else { 02656 ast_log(LOG_ERROR, "Out of memory.\n"); 02657 } 02658 02659 iks_delete(iq); 02660 02661 return res; 02662 }
| 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 3150 of file res_jabber.c.
References ast_aji_client_destroy(), ast_verb, ASTOBJ_UNREF, aji_client::p, SECURE, aji_client::ssl_context, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by unload_module().
03151 { 03152 if (client) { 03153 ast_verb(4, "JABBER: Disconnecting\n"); 03154 #ifdef HAVE_OPENSSL 03155 if (client->stream_flags & SECURE) { 03156 SSL_shutdown(client->ssl_session); 03157 SSL_CTX_free(client->ssl_context); 03158 SSL_free(client->ssl_session); 03159 } 03160 #endif 03161 iks_disconnect(client->p); 03162 iks_parser_delete(client->p); 03163 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03164 } 03165 03166 return 1; 03167 }
| 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 4572 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, and clients.
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(), and manager_jabber_send().
04573 { 04574 struct aji_client *client = NULL; 04575 char *aux = NULL; 04576 04577 client = ASTOBJ_CONTAINER_FIND(&clients, name); 04578 if (!client && strchr(name, '@')) { 04579 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04580 aux = ast_strdupa(iterator->user); 04581 if (strchr(aux, '/')) { 04582 /* strip resource for comparison */ 04583 aux = strsep(&aux, "/"); 04584 } 04585 if (!strncasecmp(aux, name, strlen(aux))) { 04586 client = ASTOBJ_REF(iterator); 04587 } 04588 }); 04589 } 04590 04591 return client; 04592 }
| struct aji_client_container* ast_aji_get_clients | ( | void | ) | [read] |
Definition at line 4594 of file res_jabber.c.
References clients.
Referenced by gtalk_load_config(), and jingle_load_config().
04595 { 04596 return &clients; 04597 }
| void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
| mid | char. |
Definition at line 2787 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().
| int ast_aji_invite_chat | ( | struct aji_client * | client, | |
| char * | user, | |||
| char * | room, | |||
| char * | message | |||
| ) |
invite to a chatroom.
Definition at line 2695 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02696 { 02697 int res = 0; 02698 iks *invite, *body, *namespace; 02699 02700 invite = iks_new("message"); 02701 body = iks_new("body"); 02702 namespace = iks_new("x"); 02703 if (client && invite && body && namespace) { 02704 iks_insert_attrib(invite, "to", user); 02705 iks_insert_attrib(invite, "id", client->mid); 02706 ast_aji_increment_mid(client->mid); 02707 iks_insert_cdata(body, message, 0); 02708 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02709 iks_insert_attrib(namespace, "jid", room); 02710 iks_insert_node(invite, body); 02711 iks_insert_node(invite, namespace); 02712 res = ast_aji_send(client, invite); 02713 } else { 02714 ast_log(LOG_ERROR, "Out of memory.\n"); 02715 } 02716 02717 iks_delete(body); 02718 iks_delete(namespace); 02719 iks_delete(invite); 02720 02721 return res; 02722 }
| 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 2671 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_join_exec().
02672 { 02673 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL); 02674 }
| 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 2683 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_leave_exec().
02684 { 02685 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL); 02686 }
| 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 1436 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().
01437 { 01438 return aji_send_raw(client, iks_string(iks_stack(x), x)); 01439 }
| 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 2579 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_send_exec(), gtalk_sendtext(), jingle_sendtext(), and manager_jabber_send().
02580 { 02581 return aji_send_raw_chat(client, 0, NULL, address, message); 02582 }
| 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 2593 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_sendgroup_exec().
02593 { 02594 return aji_send_raw_chat(client, 1, nick, address, message); 02595 }
| static int delete_old_messages | ( | struct aji_client * | client, | |
| char * | from | |||
| ) | [static] |
Definition at line 929 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, LOG_ERROR, and aji_client::message_timeout.
Referenced by aji_handle_message(), and delete_old_messages_all().
00930 { 00931 int deleted = 0; 00932 int isold = 0; 00933 struct aji_message *tmp = NULL; 00934 if (!client) { 00935 ast_log(LOG_ERROR, "Cannot find our XMPP client\n"); 00936 return -1; 00937 } 00938 00939 /* remove old messages */ 00940 AST_LIST_LOCK(&client->messages); 00941 if (AST_LIST_EMPTY(&client->messages)) { 00942 AST_LIST_UNLOCK(&client->messages); 00943 return 0; 00944 } 00945 00946 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00947 if (isold) { 00948 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00949 AST_LIST_REMOVE_CURRENT(list); 00950 aji_message_destroy(tmp); 00951 deleted ++; 00952 } 00953 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00954 isold = 1; 00955 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00956 AST_LIST_REMOVE_CURRENT(list); 00957 aji_message_destroy(tmp); 00958 deleted ++; 00959 } 00960 } 00961 } 00962 AST_LIST_TRAVERSE_SAFE_END; 00963 AST_LIST_UNLOCK(&client->messages); 00964 00965 return deleted; 00966 }
| static int delete_old_messages_all | ( | struct aji_client * | client | ) | [static] |
Definition at line 976 of file res_jabber.c.
References delete_old_messages().
Referenced by aji_recv_loop().
00977 { 00978 return delete_old_messages(client, NULL); 00979 }
| static int gtalk_yuck | ( | iks * | node | ) | [static] |
Definition at line 566 of file res_jabber.c.
References ast_debug.
Referenced by aji_handle_presence().
00567 { 00568 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) { 00569 ast_debug(1, "Found resource with Googletalk voice capabilities\n"); 00570 return 1; 00571 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) { 00572 ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n"); 00573 return 1; 00574 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) { 00575 ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n"); 00576 return 1; 00577 } 00578 00579 return 0; 00580 }
| static iks * jabber_make_auth | ( | iksid * | id, | |
| const char * | pass, | |||
| const char * | sid | |||
| ) | [static] |
Definition at line 590 of file res_jabber.c.
References ast_sha1_hash().
Referenced by aji_act_hook().
00591 { 00592 iks *x, *y; 00593 x = iks_new("iq"); 00594 iks_insert_attrib(x, "type", "set"); 00595 y = iks_insert(x, "query"); 00596 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00597 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00598 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00599 if (sid) { 00600 char buf[41]; 00601 char sidpass[100]; 00602 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00603 ast_sha1_hash(buf, sidpass); 00604 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00605 } else { 00606 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00607 } 00608 return x; 00609 }
| static int load_module | ( | void | ) | [static] |
Definition at line 4726 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_mutex_init, ast_register_application_xml, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, and manager_jabber_send().
04727 { 04728 ASTOBJ_CONTAINER_INIT(&clients); 04729 if (!aji_reload(0)) 04730 return AST_MODULE_LOAD_DECLINE; 04731 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 04732 ast_register_application_xml(app_ajisend, aji_send_exec); 04733 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec); 04734 ast_register_application_xml(app_ajistatus, aji_status_exec); 04735 ast_register_application_xml(app_ajijoin, aji_join_exec); 04736 ast_register_application_xml(app_ajileave, aji_leave_exec); 04737 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04738 ast_custom_function_register(&jabberstatus_function); 04739 ast_custom_function_register(&jabberreceive_function); 04740 04741 ast_mutex_init(&messagelock); 04742 ast_cond_init(&message_received_condition, NULL); 04743 return 0; 04744 }
| static int manager_jabber_send | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4606 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().
04607 { 04608 struct aji_client *client = NULL; 04609 const char *id = astman_get_header(m, "ActionID"); 04610 const char *jabber = astman_get_header(m, "Jabber"); 04611 const char *screenname = astman_get_header(m, "ScreenName"); 04612 const char *message = astman_get_header(m, "Message"); 04613 04614 if (ast_strlen_zero(jabber)) { 04615 astman_send_error(s, m, "No transport specified"); 04616 return 0; 04617 } 04618 if (ast_strlen_zero(screenname)) { 04619 astman_send_error(s, m, "No ScreenName specified"); 04620 return 0; 04621 } 04622 if (ast_strlen_zero(message)) { 04623 astman_send_error(s, m, "No Message specified"); 04624 return 0; 04625 } 04626 04627 astman_send_ack(s, m, "Attempting to send Jabber Message"); 04628 client = ast_aji_get_client(jabber); 04629 if (!client) { 04630 astman_send_error(s, m, "Could not find Sender"); 04631 return 0; 04632 } 04633 if (strchr(screenname, '@') && message) { 04634 ast_aji_send_chat(client, screenname, message); 04635 astman_append(s, "Response: Success\r\n"); 04636 } else { 04637 astman_append(s, "Response: Error\r\n"); 04638 } 04639 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04640 if (!ast_strlen_zero(id)) { 04641 astman_append(s, "ActionID: %s\r\n", id); 04642 } 04643 astman_append(s, "\r\n"); 04644 return 0; 04645 }
| static int reload | ( | void | ) | [static] |
Definition at line 4750 of file res_jabber.c.
References aji_reload().
04751 { 04752 aji_reload(1); 04753 return 0; 04754 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 4685 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_mutex_destroy, ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, and clients.
04686 { 04687 04688 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04689 ast_unregister_application(app_ajisend); 04690 ast_unregister_application(app_ajisendgroup); 04691 ast_unregister_application(app_ajistatus); 04692 ast_unregister_application(app_ajijoin); 04693 ast_unregister_application(app_ajileave); 04694 ast_manager_unregister("JabberSend"); 04695 ast_custom_function_unregister(&jabberstatus_function); 04696 if (mwi_sub) { 04697 ast_event_unsubscribe(mwi_sub); 04698 } 04699 if (device_state_sub) { 04700 ast_event_unsubscribe(device_state_sub); 04701 } 04702 ast_custom_function_unregister(&jabberreceive_function); 04703 04704 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04705 ASTOBJ_WRLOCK(iterator); 04706 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 04707 iterator->state = AJI_DISCONNECTING; 04708 ASTOBJ_UNLOCK(iterator); 04709 pthread_join(iterator->thread, NULL); 04710 ast_aji_disconnect(iterator); 04711 }); 04712 04713 ASTOBJ_CONTAINER_DESTROYALL(&clients, ast_aji_client_destroy); 04714 ASTOBJ_CONTAINER_DESTROY(&clients); 04715 04716 ast_cond_destroy(&message_received_condition); 04717 ast_mutex_destroy(&messagelock); 04718 04719 return 0; 04720 }
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 = "95089850e3c922fa176f9bd274fd8109" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 4761 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
Definition at line 374 of file res_jabber.c.
char* app_ajijoin = "JabberJoin" [static] |
Definition at line 389 of file res_jabber.c.
char* app_ajileave = "JabberLeave" [static] |
Definition at line 390 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 386 of file res_jabber.c.
char* app_ajisendgroup = "JabberSendGroup" [static] |
Definition at line 387 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 388 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4761 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL [static] |
Definition at line 393 of file res_jabber.c.
Referenced by ast_request().
struct aji_client_container clients [static] |
Definition at line 392 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(), 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 395 of file res_jabber.c.
struct ast_flags globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } [static] |
Global flags, initialized to default values.
Definition at line 400 of file res_jabber.c.
struct ast_custom_function jabberreceive_function [static] |
{
.name = "JABBER_RECEIVE",
.read = acf_jabberreceive_read,
}
Definition at line 915 of file res_jabber.c.
struct ast_custom_function jabberstatus_function [static] |
{
.name = "JABBER_STATUS",
.read = acf_jabberstatus_read,
}
Definition at line 753 of file res_jabber.c.
ast_cond_t message_received_condition [static] |
Definition at line 396 of file res_jabber.c.
ast_mutex_t messagelock [static] |
Definition at line 397 of file res_jabber.c.
struct ast_event_sub* mwi_sub = NULL [static] |
Definition at line 394 of file res_jabber.c.
struct ast_flags pubsubflags = { 0 } [static] |
PubSub flags, initialized to default values.
Definition at line 403 of file res_jabber.c.
1.6.1