#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) |
Build the skeleton of a publish. | |
static char * | aji_cli_create_collection (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub collection node creation via CLI. | |
static char * | aji_cli_create_leafnode (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub leaf node creation via CLI. | |
static char * | aji_cli_delete_pubsub_node (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub node deletion via CLI. | |
static char * | aji_cli_list_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub node list via CLI. | |
static char * | aji_cli_purge_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to purge PubSub nodes via CLI. | |
static int | aji_client_connect (void *data, ikspak *pak) |
static int | aji_client_info_handler (void *data, ikspak *pak) |
static void | aji_create_affiliations (struct aji_client *client, const char *node) |
Add Owner affiliations for pubsub node. | |
static int | aji_create_buddy (char *label, struct aji_client *client) |
static int | aji_create_client (char *label, struct ast_variable *var, int debug) |
static void | aji_create_pubsub_collection (struct aji_client *client, const char *collection_name) |
Create a PubSub collection node. | |
static void | aji_create_pubsub_leaf (struct aji_client *client, const char *collection_name, const char *leaf_name) |
Create a PubSub leaf node. | |
static iks * | aji_create_pubsub_node (struct aji_client *client, const char *node_type, const char *name, const char *collection_name) |
Create a pubsub node. | |
static int | aji_delete_node_list (void *data, ikspak *pak) |
Delete pubsub item lists. | |
static void | aji_delete_pubsub_node (struct aji_client *client, const char *node_name) |
Delete a PubSub node. | |
static void | aji_devstate_cb (const struct ast_event *ast_event, void *data) |
Callback function for device state events. | |
static int | aji_dinfo_handler (void *data, ikspak *pak) |
static int | aji_ditems_handler (void *data, ikspak *pak) |
static char * | aji_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | aji_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_filter_roster (void *data, ikspak *pak) |
static struct aji_resource * | aji_find_resource (struct aji_buddy *buddy, char *name) |
static struct aji_version * | aji_find_version (char *node, char *version, ikspak *pak) |
static int | aji_get_roster (struct aji_client *client) |
static void | aji_handle_iq (struct aji_client *client, iks *node) |
static void | aji_handle_message (struct aji_client *client, ikspak *pak) |
static void | aji_handle_presence (struct aji_client *client, ikspak *pak) |
static int | aji_handle_pubsub_error (void *data, ikspak *pak) |
static int | aji_handle_pubsub_event (void *data, ikspak *pak) |
Callback for handling PubSub events. | |
static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
static void | aji_init_event_distribution (struct aji_client *client) |
Initialize collections for event distribution. | |
static int | aji_initialize (struct aji_client *client) |
static int | aji_io_recv (struct aji_client *client, char *buffer, size_t buf_len, int timeout) |
static int | aji_is_secure (struct aji_client *client) |
static int | aji_join_exec (struct ast_channel *chan, const char *data) |
Application to join a chat room. | |
static int | aji_leave_exec (struct ast_channel *chan, const char *data) |
Application to leave a chat room. | |
static int | aji_load_config (int reload) |
static void | aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming) |
static void | aji_message_destroy (struct aji_message *obj) |
static void | aji_mwi_cb (const struct ast_event *ast_event, void *data) |
Callback function for MWI events. | |
static void | aji_pruneregister (struct aji_client *client) |
static void | aji_publish_device_state (struct aji_client *client, const char *device, const char *device_state) |
Publish device state to a PubSub node. | |
static void | aji_publish_mwi (struct aji_client *client, const char *mailbox, const char *context, const char *oldmsgs, const char *newmsgs) |
Publish MWI to a PubSub node. | |
static iks * | aji_pubsub_iq_create (struct aji_client *client, const char *type) |
Create an IQ packet. | |
static void | aji_pubsub_purge_nodes (struct aji_client *client, const char *collection_name) |
static void | aji_pubsub_subscribe (struct aji_client *client, const char *node) |
Subscribe to a PubSub node. | |
static int | aji_receive_node_list (void *data, ikspak *pak) |
Receive pubsub item lists. | |
static int | aji_reconnect (struct aji_client *client) |
static int | aji_recv (struct aji_client *client, int timeout) |
static void * | aji_recv_loop (void *data) |
static int | aji_register_approve_handler (void *data, ikspak *pak) |
static int | aji_register_query_handler (void *data, ikspak *pak) |
static int | aji_reload (int reload) |
static void | aji_request_pubsub_nodes (struct aji_client *client, const char *collection) |
Request item list from pubsub. | |
static int | aji_send_exec (struct ast_channel *chan, const char *data) |
static int | aji_send_header (struct aji_client *client, const char *to) |
static int | aji_send_raw (struct aji_client *client, const char *xmlstr) |
static int | aji_send_raw_chat (struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message) |
sends messages. | |
static int | aji_sendgroup_exec (struct ast_channel *chan, const char *data) |
Application to send a message to a groupchat. | |
static int | aji_set_group_presence (struct aji_client *client, char *room, int level, char *nick, char *desc) |
static void | aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc) |
static char * | aji_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | aji_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_start_sasl (struct aji_client *client, enum ikssasltype type, char *username, char *pass) |
static int | aji_start_tls (struct aji_client *client) |
static int | aji_status_exec (struct ast_channel *chan, const char *data) |
static char * | aji_test (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
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. | |
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) | |
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 = "88eaa8f5c1bd988bedd71113385e0886" , .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. |
References:
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 4784 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4784 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 769 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, messagelock, aji_client::messages, ast_channel::name, and parse().
00770 { 00771 char *aux = NULL, *parse = NULL; 00772 int timeout; 00773 int jidlen, resourcelen; 00774 struct timeval start; 00775 long diff = 0; 00776 struct aji_client *client = NULL; 00777 int found = 0; 00778 struct aji_message *tmp = NULL; 00779 AST_DECLARE_APP_ARGS(args, 00780 AST_APP_ARG(account); 00781 AST_APP_ARG(jid); 00782 AST_APP_ARG(timeout); 00783 ); 00784 AST_DECLARE_APP_ARGS(jid, 00785 AST_APP_ARG(screenname); 00786 AST_APP_ARG(resource); 00787 ); 00788 00789 if (ast_strlen_zero(data)) { 00790 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00791 return -1; 00792 } 00793 00794 parse = ast_strdupa(data); 00795 AST_STANDARD_APP_ARGS(args, parse); 00796 00797 if (args.argc < 2 || args.argc > 3) { 00798 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00799 return -1; 00800 } 00801 00802 parse = ast_strdupa(args.jid); 00803 AST_NONSTANDARD_APP_ARGS(jid, parse, '/'); 00804 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) { 00805 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse); 00806 return -1; 00807 } 00808 00809 if (ast_strlen_zero(args.timeout)) { 00810 timeout = 20; 00811 } else { 00812 sscanf(args.timeout, "%d", &timeout); 00813 if (timeout <= 0) { 00814 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 00815 return -1; 00816 } 00817 } 00818 00819 jidlen = strlen(jid.screenname); 00820 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource); 00821 00822 client = ast_aji_get_client(args.account); 00823 if (!client) { 00824 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account); 00825 return -1; 00826 } 00827 00828 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid); 00829 00830 start = ast_tvnow(); 00831 00832 if (ast_autoservice_start(chan) < 0) { 00833 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", chan->name); 00834 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00835 return -1; 00836 } 00837 00838 /* search the messages list, grab the first message that matches with 00839 * the from JID we're expecting, and remove it from the messages list */ 00840 while (diff < timeout) { 00841 struct timespec ts = { 0, }; 00842 struct timeval wait; 00843 int res; 00844 00845 wait = ast_tvadd(start, ast_tv(timeout, 0)); 00846 ts.tv_sec = wait.tv_sec; 00847 ts.tv_nsec = wait.tv_usec * 1000; 00848 00849 /* wait up to timeout seconds for an incoming message */ 00850 ast_mutex_lock(&messagelock); 00851 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts); 00852 ast_mutex_unlock(&messagelock); 00853 if (res == ETIMEDOUT) { 00854 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout); 00855 break; 00856 } 00857 00858 AST_LIST_LOCK(&client->messages); 00859 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00860 if (jid.argc == 1) { 00861 /* no resource provided, compare bare JIDs */ 00862 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00863 continue; 00864 } 00865 } else { 00866 /* resource appended, compare bare JIDs and resources */ 00867 char *resource = strchr(tmp->from, '/'); 00868 if (!resource || strlen(resource) == 0) { 00869 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from); 00870 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00871 continue; 00872 } 00873 } else { 00874 resource ++; 00875 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) { 00876 continue; 00877 } 00878 } 00879 } 00880 /* check if the message is not too old */ 00881 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00882 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from); 00883 AST_LIST_REMOVE_CURRENT(list); 00884 aji_message_destroy(tmp); 00885 continue; 00886 } 00887 found = 1; 00888 aux = ast_strdupa(tmp->message); 00889 AST_LIST_REMOVE_CURRENT(list); 00890 aji_message_destroy(tmp); 00891 break; 00892 } 00893 AST_LIST_TRAVERSE_SAFE_END; 00894 AST_LIST_UNLOCK(&client->messages); 00895 if (found) { 00896 break; 00897 } 00898 00899 /* check timeout */ 00900 diff = ast_tvdiff_ms(ast_tvnow(), start); 00901 } 00902 00903 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00904 if (ast_autoservice_stop(chan) < 0) { 00905 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", chan->name); 00906 } 00907 00908 /* return if we timed out */ 00909 if (!found) { 00910 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); 00911 return -1; 00912 } 00913 ast_copy_string(buf, aux, buflen); 00914 00915 return 0; 00916 }
static int acf_jabberstatus_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 698 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.
00699 { 00700 struct aji_client *client = NULL; 00701 struct aji_buddy *buddy = NULL; 00702 struct aji_resource *r = NULL; 00703 int stat = 7; 00704 AST_DECLARE_APP_ARGS(args, 00705 AST_APP_ARG(sender); 00706 AST_APP_ARG(jid); 00707 ); 00708 AST_DECLARE_APP_ARGS(jid, 00709 AST_APP_ARG(screenname); 00710 AST_APP_ARG(resource); 00711 ); 00712 00713 if (!data) { 00714 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00715 return 0; 00716 } 00717 AST_STANDARD_APP_ARGS(args, data); 00718 00719 if (args.argc != 2) { 00720 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00721 return -1; 00722 } 00723 00724 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00725 if (jid.argc < 1 || jid.argc > 2) { 00726 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00727 return -1; 00728 } 00729 00730 if (!(client = ast_aji_get_client(args.sender))) { 00731 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00732 return -1; 00733 } 00734 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00735 if (!buddy) { 00736 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00737 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00738 return -1; 00739 } 00740 r = aji_find_resource(buddy, jid.resource); 00741 if (!r && buddy->resources) { 00742 r = buddy->resources; 00743 } 00744 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00745 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00746 if (!r) { 00747 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00748 } else { 00749 stat = r->status; 00750 } 00751 snprintf(buf, buflen, "%d", stat); 00752 return 0; 00753 }
static int aji_act_hook | ( | void * | data, | |
int | type, | |||
iks * | node | |||
) | [static] |
Definition at line 1572 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(), asprintf, ast_aji_client_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_debug, ast_free, ast_log(), ast_sha1_hash(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::authorized, aji_client::component, aji_client::f, jabber_make_auth(), aji_client::jid, LOG_ERROR, LOG_WARNING, aji_client::mid, aji_client::password, secret, aji_client::state, aji_client::stream_flags, aji_client::usesasl, and aji_client::usetls.
Referenced by aji_create_client().
01573 { 01574 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01575 ikspak *pak = NULL; 01576 iks *auth = NULL; 01577 int features = 0; 01578 01579 if (!node) { 01580 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 01581 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01582 return IKS_HOOK; 01583 } 01584 01585 if (client->state == AJI_DISCONNECTING) { 01586 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01587 return IKS_HOOK; 01588 } 01589 01590 pak = iks_packet(node); 01591 01592 /* work around iksemel's impossibility to recognize node names 01593 * containing a semicolon. Set the namespace of the corresponding 01594 * node accordingly. */ 01595 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) { 01596 char *node_ns = NULL; 01597 char attr[AJI_MAX_ATTRLEN]; 01598 char *node_name = iks_name(iks_child(node)); 01599 char *aux = strchr(node_name, ':') + 1; 01600 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name); 01601 node_ns = iks_find_attrib(iks_child(node), attr); 01602 if (node_ns) { 01603 pak->ns = node_ns; 01604 pak->query = iks_child(node); 01605 } 01606 } 01607 01608 01609 if (!client->component) { /*client */ 01610 switch (type) { 01611 case IKS_NODE_START: 01612 if (client->usetls && !aji_is_secure(client)) { 01613 #ifndef HAVE_OPENSSL 01614 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"); 01615 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01616 return IKS_HOOK; 01617 #else 01618 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 01619 ast_log(LOG_ERROR, "Could not start TLS\n"); 01620 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01621 return IKS_HOOK; 01622 } 01623 #endif 01624 break; 01625 } 01626 if (!client->usesasl) { 01627 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); 01628 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 01629 if (auth) { 01630 iks_insert_attrib(auth, "id", client->mid); 01631 iks_insert_attrib(auth, "to", client->jid->server); 01632 ast_aji_increment_mid(client->mid); 01633 ast_aji_send(client, auth); 01634 iks_delete(auth); 01635 } else { 01636 ast_log(LOG_ERROR, "Out of memory.\n"); 01637 } 01638 } 01639 break; 01640 01641 case IKS_NODE_NORMAL: 01642 #ifdef HAVE_OPENSSL 01643 if (client->stream_flags & TRY_SECURE) { 01644 if (!strcmp("proceed", iks_name(node))) { 01645 return aji_tls_handshake(client); 01646 } 01647 } 01648 #endif 01649 if (!strcmp("stream:features", iks_name(node))) { 01650 features = iks_stream_features(node); 01651 if (client->usesasl) { 01652 if (client->usetls && !aji_is_secure(client)) { 01653 break; 01654 } 01655 if (client->authorized) { 01656 if (features & IKS_STREAM_BIND) { 01657 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); 01658 auth = iks_make_resource_bind(client->jid); 01659 if (auth) { 01660 iks_insert_attrib(auth, "id", client->mid); 01661 ast_aji_increment_mid(client->mid); 01662 ast_aji_send(client, auth); 01663 iks_delete(auth); 01664 } else { 01665 ast_log(LOG_ERROR, "Out of memory.\n"); 01666 break; 01667 } 01668 } 01669 if (features & IKS_STREAM_SESSION) { 01670 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); 01671 auth = iks_make_session(); 01672 if (auth) { 01673 iks_insert_attrib(auth, "id", "auth"); 01674 ast_aji_increment_mid(client->mid); 01675 ast_aji_send(client, auth); 01676 iks_delete(auth); 01677 } else { 01678 ast_log(LOG_ERROR, "Out of memory.\n"); 01679 } 01680 } 01681 } else { 01682 int ret; 01683 if (!client->jid->user) { 01684 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 01685 break; 01686 } 01687 01688 ret = aji_start_sasl(client, features, client->jid->user, client->password); 01689 if (ret != IKS_OK) { 01690 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01691 return IKS_HOOK; 01692 } 01693 break; 01694 } 01695 } 01696 } else if (!strcmp("failure", iks_name(node))) { 01697 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 01698 } else if (!strcmp("success", iks_name(node))) { 01699 client->authorized = 1; 01700 aji_send_header(client, client->jid->server); 01701 } 01702 break; 01703 case IKS_NODE_ERROR: 01704 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01705 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01706 return IKS_HOOK; 01707 break; 01708 case IKS_NODE_STOP: 01709 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01710 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01711 return IKS_HOOK; 01712 break; 01713 } 01714 } else if (client->state != AJI_CONNECTED && client->component) { 01715 switch (type) { 01716 case IKS_NODE_START: 01717 if (client->state == AJI_DISCONNECTED) { 01718 char secret[160], shasum[320], *handshake; 01719 01720 sprintf(secret, "%s%s", pak->id, client->password); 01721 ast_sha1_hash(shasum, secret); 01722 handshake = NULL; 01723 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01724 aji_send_raw(client, handshake); 01725 ast_free(handshake); 01726 handshake = NULL; 01727 } 01728 client->state = AJI_CONNECTING; 01729 if (aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01730 client->state = AJI_CONNECTED; 01731 else 01732 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01733 break; 01734 } 01735 break; 01736 01737 case IKS_NODE_NORMAL: 01738 break; 01739 01740 case IKS_NODE_ERROR: 01741 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01742 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01743 return IKS_HOOK; 01744 01745 case IKS_NODE_STOP: 01746 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01747 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01748 return IKS_HOOK; 01749 } 01750 } 01751 01752 switch (pak->type) { 01753 case IKS_PAK_NONE: 01754 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01755 break; 01756 case IKS_PAK_MESSAGE: 01757 aji_handle_message(client, pak); 01758 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01759 break; 01760 case IKS_PAK_PRESENCE: 01761 aji_handle_presence(client, pak); 01762 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01763 break; 01764 case IKS_PAK_S10N: 01765 aji_handle_subscribe(client, pak); 01766 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01767 break; 01768 case IKS_PAK_IQ: 01769 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01770 aji_handle_iq(client, node); 01771 break; 01772 default: 01773 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01774 break; 01775 } 01776 01777 iks_filter_packet(client->f, pak); 01778 01779 if (node) 01780 iks_delete(node); 01781 01782 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01783 return IKS_OK; 01784 }
static iks * aji_build_node_config | ( | iks * | pubsub, | |
const char * | node_type, | |||
const char * | collection_name | |||
) | [static] |
Definition at line 3812 of file res_jabber.c.
Referenced by aji_create_pubsub_node().
03813 { 03814 iks *configure, *x, *field_owner, *field_node_type, *field_node_config, 03815 *field_deliver_payload, *field_persist_items, *field_access_model, 03816 *field_pubsub_collection; 03817 configure = iks_insert(pubsub, "configure"); 03818 x = iks_insert(configure, "x"); 03819 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03820 iks_insert_attrib(x, "type", "submit"); 03821 field_owner = iks_insert(x, "field"); 03822 iks_insert_attrib(field_owner, "var", "FORM_TYPE"); 03823 iks_insert_attrib(field_owner, "type", "hidden"); 03824 iks_insert_cdata(iks_insert(field_owner, "value"), 03825 "http://jabber.org/protocol/pubsub#owner", 39); 03826 if (node_type) { 03827 field_node_type = iks_insert(x, "field"); 03828 iks_insert_attrib(field_node_type, "var", "pubsub#node_type"); 03829 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type)); 03830 } 03831 field_node_config = iks_insert(x, "field"); 03832 iks_insert_attrib(field_node_config, "var", "FORM_TYPE"); 03833 iks_insert_attrib(field_node_config, "type", "hidden"); 03834 iks_insert_cdata(iks_insert(field_node_config, "value"), 03835 "http://jabber.org/protocol/pubsub#node_config", 45); 03836 field_deliver_payload = iks_insert(x, "field"); 03837 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads"); 03838 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1); 03839 field_persist_items = iks_insert(x, "field"); 03840 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items"); 03841 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1); 03842 field_access_model = iks_insert(x, "field"); 03843 iks_insert_attrib(field_access_model, "var", "pubsub#access_model"); 03844 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9); 03845 if (node_type && !strcasecmp(node_type, "leaf")) { 03846 field_pubsub_collection = iks_insert(x, "field"); 03847 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection"); 03848 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name, 03849 strlen(collection_name)); 03850 } 03851 return configure; 03852 }
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 3542 of file res_jabber.c.
References aji_pubsub_iq_create().
Referenced by aji_pubsub_purge_nodes(), and aji_request_pubsub_nodes().
03543 { 03544 iks *request = aji_pubsub_iq_create(client, "get"); 03545 iks *query; 03546 query = iks_insert(request, "query"); 03547 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 03548 if (collection) { 03549 iks_insert_attrib(query, "node", collection); 03550 } 03551 return request; 03552 }
static iks * aji_build_publish_skeleton | ( | struct aji_client * | client, | |
const char * | node, | |||
const char * | event_type | |||
) | [static] |
Build the skeleton of a publish.
client | the configured XMPP client we use to connect to a XMPP server | |
node | Name of the node that will be published to | |
event_type |
Definition at line 3370 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_test_flag, and globalflags.
Referenced by aji_publish_device_state(), and aji_publish_mwi().
03372 { 03373 iks *request = aji_pubsub_iq_create(client, "set"); 03374 iks *pubsub, *publish, *item; 03375 pubsub = iks_insert(request, "pubsub"); 03376 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03377 publish = iks_insert(pubsub, "publish"); 03378 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03379 iks_insert_attrib(publish, "node", node); 03380 } else { 03381 iks_insert_attrib(publish, "node", event_type); 03382 } 03383 item = iks_insert(publish, "item"); 03384 iks_insert_attrib(item, "id", node); 03385 return item; 03386 03387 }
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 3860 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.
03861 { 03862 struct aji_client *client; 03863 const char *name; 03864 const char *collection_name; 03865 03866 switch (cmd) { 03867 case CLI_INIT: 03868 e->command = "jabber create collection"; 03869 e->usage = 03870 "Usage: jabber create collection <connection> <collection>\n" 03871 " Creates a PubSub collection node using the account\n" 03872 " as configured in jabber.conf.\n"; 03873 return NULL; 03874 case CLI_GENERATE: 03875 return NULL; 03876 } 03877 03878 if (a->argc != 5) { 03879 return CLI_SHOWUSAGE; 03880 } 03881 name = a->argv[3]; 03882 collection_name = a->argv[4]; 03883 03884 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03885 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03886 return CLI_FAILURE; 03887 } 03888 03889 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03890 aji_create_pubsub_collection(client, collection_name); 03891 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03892 return CLI_SUCCESS; 03893 }
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 3899 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.
03900 { 03901 struct aji_client *client; 03902 const char *name; 03903 const char *collection_name; 03904 const char *leaf_name; 03905 03906 switch (cmd) { 03907 case CLI_INIT: 03908 e->command = "jabber create leaf"; 03909 e->usage = 03910 "Usage: jabber create leaf <connection> <collection> <leaf>\n" 03911 " Creates a PubSub leaf node using the account\n" 03912 " as configured in jabber.conf.\n"; 03913 return NULL; 03914 case CLI_GENERATE: 03915 return NULL; 03916 } 03917 03918 if (a->argc != 6) { 03919 return CLI_SHOWUSAGE; 03920 } 03921 name = a->argv[3]; 03922 collection_name = a->argv[4]; 03923 leaf_name = a->argv[5]; 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_leaf(client, collection_name, leaf_name); 03932 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03933 return CLI_SUCCESS; 03934 }
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 3713 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.
03715 { 03716 struct aji_client *client; 03717 const char *name; 03718 03719 switch (cmd) { 03720 case CLI_INIT: 03721 e->command = "jabber delete node"; 03722 e->usage = 03723 "Usage: jabber delete node <connection> <node>\n" 03724 " Deletes a node on PubSub server\n" 03725 " as configured in jabber.conf.\n"; 03726 return NULL; 03727 case CLI_GENERATE: 03728 return NULL; 03729 } 03730 03731 if (a->argc != 5) { 03732 return CLI_SHOWUSAGE; 03733 } 03734 name = a->argv[3]; 03735 03736 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03737 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03738 return CLI_FAILURE; 03739 } 03740 aji_delete_pubsub_node(client, a->argv[4]); 03741 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03742 return CLI_SUCCESS; 03743 }
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 3588 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.
03590 { 03591 struct aji_client *client; 03592 const char *name = NULL; 03593 const char *collection = NULL; 03594 03595 switch (cmd) { 03596 case CLI_INIT: 03597 e->command = "jabber list nodes"; 03598 e->usage = 03599 "Usage: jabber list nodes <connection> [collection]\n" 03600 " Lists the user's nodes on the respective connection\n" 03601 " ([connection] as configured in jabber.conf.)\n"; 03602 return NULL; 03603 case CLI_GENERATE: 03604 return NULL; 03605 } 03606 03607 if (a->argc > 5 || a->argc < 4) { 03608 return CLI_SHOWUSAGE; 03609 } else if (a->argc == 4 || a->argc == 5) { 03610 name = a->argv[3]; 03611 } 03612 if (a->argc == 5) { 03613 collection = a->argv[4]; 03614 } 03615 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03616 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03617 return CLI_FAILURE; 03618 } 03619 03620 ast_cli(a->fd, "Listing pubsub nodes.\n"); 03621 aji_request_pubsub_nodes(client, collection); 03622 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03623 return CLI_SUCCESS; 03624 }
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 3633 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, pubsubflags, and ast_cli_entry::usage.
03635 { 03636 struct aji_client *client; 03637 const char *name; 03638 03639 switch (cmd) { 03640 case CLI_INIT: 03641 e->command = "jabber purge nodes"; 03642 e->usage = 03643 "Usage: jabber purge nodes <connection> <node>\n" 03644 " Purges nodes on PubSub server\n" 03645 " as configured in jabber.conf.\n"; 03646 return NULL; 03647 case CLI_GENERATE: 03648 return NULL; 03649 } 03650 03651 if (a->argc != 5) { 03652 return CLI_SHOWUSAGE; 03653 } 03654 name = a->argv[3]; 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 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03661 aji_pubsub_purge_nodes(client, a->argv[4]); 03662 } else { 03663 aji_delete_pubsub_node(client, a->argv[4]); 03664 } 03665 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03666 return CLI_SUCCESS; 03667 }
static int aji_client_connect | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3079 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().
03080 { 03081 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03082 int res = IKS_FILTER_PASS; 03083 03084 if (client) { 03085 if (client->state == AJI_DISCONNECTED) { 03086 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); 03087 client->state = AJI_CONNECTING; 03088 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 03089 if (!client->component) { /*client*/ 03090 aji_get_roster(client); 03091 } 03092 if (client->distribute_events) { 03093 aji_init_event_distribution(client); 03094 } 03095 03096 iks_filter_remove_hook(client->f, aji_client_connect); 03097 /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ 03098 res = IKS_FILTER_EAT; 03099 } 03100 } else { 03101 ast_log(LOG_ERROR, "Out of memory.\n"); 03102 } 03103 03104 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03105 return res; 03106 }
static int aji_client_info_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2005 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().
02006 { 02007 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02008 struct aji_resource *resource = NULL; 02009 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02010 02011 resource = aji_find_resource(buddy, pak->from->resource); 02012 if (pak->subtype == IKS_TYPE_RESULT) { 02013 if (!resource) { 02014 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02015 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02016 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02017 return IKS_FILTER_EAT; 02018 } 02019 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02020 resource->cap->jingle = 1; 02021 } else { 02022 resource->cap->jingle = 0; 02023 } 02024 } else if (pak->subtype == IKS_TYPE_GET) { 02025 iks *iq, *disco, *ident, *google, *query; 02026 iq = iks_new("iq"); 02027 query = iks_new("query"); 02028 ident = iks_new("identity"); 02029 disco = iks_new("feature"); 02030 google = iks_new("feature"); 02031 if (iq && ident && disco && google) { 02032 iks_insert_attrib(iq, "from", client->jid->full); 02033 iks_insert_attrib(iq, "to", pak->from->full); 02034 iks_insert_attrib(iq, "type", "result"); 02035 iks_insert_attrib(iq, "id", pak->id); 02036 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02037 iks_insert_attrib(ident, "category", "client"); 02038 iks_insert_attrib(ident, "type", "pc"); 02039 iks_insert_attrib(ident, "name", "asterisk"); 02040 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 02041 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 02042 iks_insert_node(iq, query); 02043 iks_insert_node(query, ident); 02044 iks_insert_node(query, google); 02045 iks_insert_node(query, disco); 02046 ast_aji_send(client, iq); 02047 } else { 02048 ast_log(LOG_ERROR, "Out of Memory.\n"); 02049 } 02050 02051 iks_delete(iq); 02052 iks_delete(query); 02053 iks_delete(ident); 02054 iks_delete(google); 02055 iks_delete(disco); 02056 } else if (pak->subtype == IKS_TYPE_ERROR) { 02057 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 02058 } 02059 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02060 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02061 return IKS_FILTER_EAT; 02062 }
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 3306 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().
03307 { 03308 iks *modify_affiliates = aji_pubsub_iq_create(client, "set"); 03309 iks *pubsub, *affiliations, *affiliate; 03310 pubsub = iks_insert(modify_affiliates, "pubsub"); 03311 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03312 affiliations = iks_insert(pubsub, "affiliations"); 03313 iks_insert_attrib(affiliations, "node", node); 03314 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03315 ASTOBJ_RDLOCK(iterator); 03316 affiliate = iks_insert(affiliations, "affiliation"); 03317 iks_insert_attrib(affiliate, "jid", iterator->name); 03318 iks_insert_attrib(affiliate, "affiliation", "owner"); 03319 ASTOBJ_UNLOCK(iterator); 03320 }); 03321 ast_aji_send(client, modify_affiliates); 03322 iks_delete(modify_affiliates); 03323 }
static int aji_create_buddy | ( | char * | label, | |
struct aji_client * | client | |||
) | [static] |
load config file.
Definition at line 4510 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 4255 of file res_jabber.c.
References aji_act_hook(), AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), AJI_PUBSUB, aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_aji_client_destroy(), ast_calloc, ast_clear_flag, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, ast_free, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_set_flag, ast_test_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::distribute_events, aji_client::f, aji_client::flags, aji_client::forcessl, globalflags, aji_client::jid, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, aji_client::name, aji_client::name_space, aji_client::p, aji_client::password, aji_client::port, aji_client::priority, aji_client::pubsub_node, pubsubflags, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and var.
04256 { 04257 char *resource; 04258 struct aji_client *client = NULL; 04259 int flag = 0; 04260 04261 client = ASTOBJ_CONTAINER_FIND(&clients, label); 04262 if (!client) { 04263 flag = 1; 04264 client = ast_calloc(1, sizeof(*client)); 04265 if (!client) { 04266 ast_log(LOG_ERROR, "Out of memory!\n"); 04267 return 0; 04268 } 04269 ASTOBJ_INIT(client); 04270 ASTOBJ_WRLOCK(client); 04271 ASTOBJ_CONTAINER_INIT(&client->buddies); 04272 } else { 04273 ASTOBJ_WRLOCK(client); 04274 ASTOBJ_UNMARK(client); 04275 } 04276 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 04277 ast_copy_string(client->name, label, sizeof(client->name)); 04278 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 04279 04280 /* Set default values for the client object */ 04281 client->debug = debug; 04282 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 04283 client->port = 5222; 04284 client->usetls = 1; 04285 client->usesasl = 1; 04286 client->forcessl = 0; 04287 client->keepalive = 1; 04288 client->timeout = 50; 04289 client->message_timeout = 5; 04290 client->distribute_events = 0; 04291 AST_LIST_HEAD_INIT(&client->messages); 04292 client->component = 0; 04293 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 04294 client->priority = 0; 04295 client->status = IKS_SHOW_AVAILABLE; 04296 04297 if (flag) { 04298 client->authorized = 0; 04299 client->state = AJI_DISCONNECTED; 04300 } 04301 while (var) { 04302 if (!strcasecmp(var->name, "username")) { 04303 ast_copy_string(client->user, var->value, sizeof(client->user)); 04304 } else if (!strcasecmp(var->name, "serverhost")) { 04305 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 04306 } else if (!strcasecmp(var->name, "secret")) { 04307 ast_copy_string(client->password, var->value, sizeof(client->password)); 04308 } else if (!strcasecmp(var->name, "statusmessage")) { 04309 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 04310 } else if (!strcasecmp(var->name, "port")) { 04311 client->port = atoi(var->value); 04312 } else if (!strcasecmp(var->name, "timeout")) { 04313 client->message_timeout = atoi(var->value); 04314 } else if (!strcasecmp(var->name, "debug")) { 04315 client->debug = (ast_false(var->value)) ? 0 : 1; 04316 } else if (!strcasecmp(var->name, "type")) { 04317 if (!strcasecmp(var->value, "component")) { 04318 client->component = 1; 04319 if (client->distribute_events) { 04320 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04321 client->distribute_events = 0; 04322 } 04323 } 04324 } else if (!strcasecmp(var->name, "distribute_events")) { 04325 if (ast_true(var->value)) { 04326 if (client->component) { 04327 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04328 } else { 04329 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) { 04330 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n"); 04331 } else { 04332 ast_set_flag(&pubsubflags, AJI_PUBSUB); 04333 client->distribute_events = 1; 04334 } 04335 } 04336 } 04337 } else if (!strcasecmp(var->name, "pubsub_node")) { 04338 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node)); 04339 } else if (!strcasecmp(var->name, "usetls")) { 04340 client->usetls = (ast_false(var->value)) ? 0 : 1; 04341 } else if (!strcasecmp(var->name, "usesasl")) { 04342 client->usesasl = (ast_false(var->value)) ? 0 : 1; 04343 } else if (!strcasecmp(var->name, "forceoldssl")) { 04344 client->forcessl = (ast_false(var->value)) ? 0 : 1; 04345 } else if (!strcasecmp(var->name, "keepalive")) { 04346 client->keepalive = (ast_false(var->value)) ? 0 : 1; 04347 } else if (!strcasecmp(var->name, "autoprune")) { 04348 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 04349 } else if (!strcasecmp(var->name, "autoregister")) { 04350 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 04351 } else if (!strcasecmp(var->name, "auth_policy")) { 04352 if (!strcasecmp(var->value, "accept")) { 04353 ast_set_flag(&client->flags, AJI_AUTOACCEPT); 04354 } else { 04355 ast_clear_flag(&client->flags, AJI_AUTOACCEPT); 04356 } 04357 } else if (!strcasecmp(var->name, "buddy")) { 04358 aji_create_buddy((char *)var->value, client); 04359 } else if (!strcasecmp(var->name, "priority")) { 04360 client->priority = atoi(var->value); 04361 } else if (!strcasecmp(var->name, "status")) { 04362 if (!strcasecmp(var->value, "unavailable")) { 04363 client->status = IKS_SHOW_UNAVAILABLE; 04364 } else if (!strcasecmp(var->value, "available") 04365 || !strcasecmp(var->value, "online")) { 04366 client->status = IKS_SHOW_AVAILABLE; 04367 } else if (!strcasecmp(var->value, "chat") 04368 || !strcasecmp(var->value, "chatty")) { 04369 client->status = IKS_SHOW_CHAT; 04370 } else if (!strcasecmp(var->value, "away")) { 04371 client->status = IKS_SHOW_AWAY; 04372 } else if (!strcasecmp(var->value, "xa") 04373 || !strcasecmp(var->value, "xaway")) { 04374 client->status = IKS_SHOW_XA; 04375 } else if (!strcasecmp(var->value, "dnd")) { 04376 client->status = IKS_SHOW_DND; 04377 } else if (!strcasecmp(var->value, "invisible")) { 04378 #ifdef IKS_SHOW_INVISIBLE 04379 client->status = IKS_SHOW_INVISIBLE; 04380 #else 04381 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 04382 client->status = IKS_SHOW_DND; 04383 #endif 04384 } else { 04385 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 04386 } 04387 } 04388 /* no transport support in this version */ 04389 /* else if (!strcasecmp(var->name, "transport")) 04390 aji_create_transport(var->value, client); 04391 */ 04392 var = var->next; 04393 } 04394 if (!flag) { 04395 ASTOBJ_UNLOCK(client); 04396 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04397 return 1; 04398 } 04399 04400 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 04401 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 04402 if (!client->p) { 04403 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 04404 return 0; 04405 } 04406 client->stack = iks_stack_new(8192, 8192); 04407 if (!client->stack) { 04408 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 04409 return 0; 04410 } 04411 client->f = iks_filter_new(); 04412 if (!client->f) { 04413 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 04414 return 0; 04415 } 04416 if (!strchr(client->user, '/') && !client->component) { /*client */ 04417 resource = NULL; 04418 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 04419 client->jid = iks_id_new(client->stack, resource); 04420 ast_free(resource); 04421 } 04422 } else { 04423 client->jid = iks_id_new(client->stack, client->user); 04424 } 04425 if (client->component) { 04426 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04427 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 04428 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); 04429 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); 04430 } else { 04431 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04432 } 04433 04434 iks_set_log_hook(client->p, aji_log_hook); 04435 ASTOBJ_UNLOCK(client); 04436 ASTOBJ_CONTAINER_LINK(&clients, client); 04437 return 1; 04438 }
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 3768 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_collection(), and aji_handle_pubsub_error().
03770 { 03771 aji_create_pubsub_node(client, "collection", collection_name, NULL); 03772 }
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 3781 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_leafnode(), and aji_handle_pubsub_error().
03783 { 03784 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name); 03785 }
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 3794 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().
03796 { 03797 iks *node = aji_pubsub_iq_create(client, "set"); 03798 iks *pubsub, *create; 03799 pubsub = iks_insert(node, "pubsub"); 03800 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03801 create = iks_insert(pubsub, "create"); 03802 iks_insert_attrib(create, "node", name); 03803 aji_build_node_config(pubsub, node_type, collection_name); 03804 ast_aji_send(client, node); 03805 aji_create_affiliations(client, name); 03806 iks_delete(node); 03807 return 0; 03808 }
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 3686 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().
03687 { 03688 03689 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03690 iks *item = NULL; 03691 if (iks_has_children(pak->query)) { 03692 item = iks_first_tag(pak->query); 03693 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial, 03694 iks_find_attrib(item, "node")); 03695 while ((item = iks_next_tag(item))) { 03696 aji_delete_pubsub_node(client, iks_find_attrib(item, "node")); 03697 } 03698 } 03699 if (item) { 03700 iks_delete(item); 03701 } 03702 return IKS_FILTER_EAT; 03703 }
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 3751 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().
03752 { 03753 iks *request = aji_pubsub_iq_create(client, "set"); 03754 iks *pubsub, *delete; 03755 pubsub = iks_insert(request, "pubsub"); 03756 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03757 delete = iks_insert(pubsub, "delete"); 03758 iks_insert_attrib(delete, "node", node_name); 03759 ast_aji_send(client, request); 03760 }
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 3198 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_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, and LOG_DEBUG.
Referenced by aji_init_event_distribution().
03199 { 03200 const char *device; 03201 const char *device_state; 03202 struct aji_client *client; 03203 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03204 { 03205 /* If the event didn't originate from this server, don't send it back out. */ 03206 ast_log(LOG_DEBUG, "Returning here\n"); 03207 return; 03208 } 03209 03210 client = ASTOBJ_REF((struct aji_client *) data); 03211 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); 03212 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); 03213 aji_publish_device_state(client, device, device_state); 03214 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03215 }
static int aji_dinfo_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2071 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().
02072 { 02073 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02074 char *node = NULL; 02075 struct aji_resource *resource = NULL; 02076 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02077 02078 if (pak->subtype == IKS_TYPE_ERROR) { 02079 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 02080 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02081 return IKS_FILTER_EAT; 02082 } 02083 resource = aji_find_resource(buddy, pak->from->resource); 02084 if (pak->subtype == IKS_TYPE_RESULT) { 02085 if (!resource) { 02086 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02087 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02088 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02089 return IKS_FILTER_EAT; 02090 } 02091 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02092 resource->cap->jingle = 1; 02093 } else { 02094 resource->cap->jingle = 0; 02095 } 02096 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 02097 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 02098 02099 iq = iks_new("iq"); 02100 query = iks_new("query"); 02101 identity = iks_new("identity"); 02102 disco = iks_new("feature"); 02103 reg = iks_new("feature"); 02104 commands = iks_new("feature"); 02105 gateway = iks_new("feature"); 02106 version = iks_new("feature"); 02107 vcard = iks_new("feature"); 02108 search = iks_new("feature"); 02109 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 02110 iks_insert_attrib(iq, "from", client->user); 02111 iks_insert_attrib(iq, "to", pak->from->full); 02112 iks_insert_attrib(iq, "id", pak->id); 02113 iks_insert_attrib(iq, "type", "result"); 02114 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02115 iks_insert_attrib(identity, "category", "gateway"); 02116 iks_insert_attrib(identity, "type", "pstn"); 02117 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 02118 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 02119 iks_insert_attrib(reg, "var", "jabber:iq:register"); 02120 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 02121 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 02122 iks_insert_attrib(version, "var", "jabber:iq:version"); 02123 iks_insert_attrib(vcard, "var", "vcard-temp"); 02124 iks_insert_attrib(search, "var", "jabber:iq:search"); 02125 02126 iks_insert_node(iq, query); 02127 iks_insert_node(query, identity); 02128 iks_insert_node(query, disco); 02129 iks_insert_node(query, reg); 02130 iks_insert_node(query, commands); 02131 iks_insert_node(query, gateway); 02132 iks_insert_node(query, version); 02133 iks_insert_node(query, vcard); 02134 iks_insert_node(query, search); 02135 ast_aji_send(client, iq); 02136 } else { 02137 ast_log(LOG_ERROR, "Out of memory.\n"); 02138 } 02139 02140 iks_delete(iq); 02141 iks_delete(query); 02142 iks_delete(identity); 02143 iks_delete(disco); 02144 iks_delete(reg); 02145 iks_delete(commands); 02146 iks_delete(gateway); 02147 iks_delete(version); 02148 iks_delete(vcard); 02149 iks_delete(search); 02150 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 02151 iks *iq, *query, *confirm; 02152 iq = iks_new("iq"); 02153 query = iks_new("query"); 02154 confirm = iks_new("item"); 02155 02156 if (iq && query && confirm && client) { 02157 iks_insert_attrib(iq, "from", client->user); 02158 iks_insert_attrib(iq, "to", pak->from->full); 02159 iks_insert_attrib(iq, "id", pak->id); 02160 iks_insert_attrib(iq, "type", "result"); 02161 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 02162 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 02163 iks_insert_attrib(confirm, "node", "confirmaccount"); 02164 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 02165 iks_insert_attrib(confirm, "jid", client->user); 02166 iks_insert_node(iq, query); 02167 iks_insert_node(query, confirm); 02168 ast_aji_send(client, iq); 02169 } else { 02170 ast_log(LOG_ERROR, "Out of memory.\n"); 02171 } 02172 02173 iks_delete(iq); 02174 iks_delete(query); 02175 iks_delete(confirm); 02176 02177 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 02178 iks *iq, *query, *feature; 02179 02180 iq = iks_new("iq"); 02181 query = iks_new("query"); 02182 feature = iks_new("feature"); 02183 02184 if (iq && query && feature && client) { 02185 iks_insert_attrib(iq, "from", client->user); 02186 iks_insert_attrib(iq, "to", pak->from->full); 02187 iks_insert_attrib(iq, "id", pak->id); 02188 iks_insert_attrib(iq, "type", "result"); 02189 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02190 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 02191 iks_insert_node(iq, query); 02192 iks_insert_node(query, feature); 02193 ast_aji_send(client, iq); 02194 } else { 02195 ast_log(LOG_ERROR, "Out of memory.\n"); 02196 } 02197 02198 iks_delete(iq); 02199 iks_delete(query); 02200 iks_delete(feature); 02201 } 02202 02203 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02204 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02205 return IKS_FILTER_EAT; 02206 }
static int aji_ditems_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1908 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().
01909 { 01910 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01911 char *node = NULL; 01912 01913 if (!(node = iks_find_attrib(pak->query, "node"))) { 01914 iks *iq = NULL, *query = NULL, *item = NULL; 01915 iq = iks_new("iq"); 01916 query = iks_new("query"); 01917 item = iks_new("item"); 01918 01919 if (iq && query && item) { 01920 iks_insert_attrib(iq, "from", client->user); 01921 iks_insert_attrib(iq, "to", pak->from->full); 01922 iks_insert_attrib(iq, "id", pak->id); 01923 iks_insert_attrib(iq, "type", "result"); 01924 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01925 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01926 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01927 iks_insert_attrib(item, "jid", client->user); 01928 01929 iks_insert_node(iq, query); 01930 iks_insert_node(query, item); 01931 ast_aji_send(client, iq); 01932 } else { 01933 ast_log(LOG_ERROR, "Out of memory.\n"); 01934 } 01935 01936 iks_delete(iq); 01937 iks_delete(query); 01938 iks_delete(item); 01939 01940 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01941 iks *iq, *query, *confirm; 01942 iq = iks_new("iq"); 01943 query = iks_new("query"); 01944 confirm = iks_new("item"); 01945 if (iq && query && confirm && client) { 01946 iks_insert_attrib(iq, "from", client->user); 01947 iks_insert_attrib(iq, "to", pak->from->full); 01948 iks_insert_attrib(iq, "id", pak->id); 01949 iks_insert_attrib(iq, "type", "result"); 01950 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01951 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01952 iks_insert_attrib(confirm, "node", "confirmaccount"); 01953 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01954 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01955 01956 iks_insert_node(iq, query); 01957 iks_insert_node(query, confirm); 01958 ast_aji_send(client, iq); 01959 } else { 01960 ast_log(LOG_ERROR, "Out of memory.\n"); 01961 } 01962 01963 iks_delete(iq); 01964 iks_delete(query); 01965 iks_delete(confirm); 01966 01967 } else if (!strcasecmp(node, "confirmaccount")) { 01968 iks *iq = NULL, *query = NULL, *feature = NULL; 01969 01970 iq = iks_new("iq"); 01971 query = iks_new("query"); 01972 feature = iks_new("feature"); 01973 01974 if (iq && query && feature && client) { 01975 iks_insert_attrib(iq, "from", client->user); 01976 iks_insert_attrib(iq, "to", pak->from->full); 01977 iks_insert_attrib(iq, "id", pak->id); 01978 iks_insert_attrib(iq, "type", "result"); 01979 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01980 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01981 iks_insert_node(iq, query); 01982 iks_insert_node(query, feature); 01983 ast_aji_send(client, iq); 01984 } else { 01985 ast_log(LOG_ERROR, "Out of memory.\n"); 01986 } 01987 01988 iks_delete(iq); 01989 iks_delete(query); 01990 iks_delete(feature); 01991 } 01992 01993 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01994 return IKS_FILTER_EAT; 01995 01996 }
static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4073 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.
04074 { 04075 switch (cmd) { 04076 case CLI_INIT: 04077 e->command = "jabber reload"; 04078 e->usage = 04079 "Usage: jabber reload\n" 04080 " Reloads the Jabber module.\n"; 04081 return NULL; 04082 case CLI_GENERATE: 04083 return NULL; 04084 } 04085 04086 aji_reload(1); 04087 ast_cli(a->fd, "Jabber Reloaded.\n"); 04088 return CLI_SUCCESS; 04089 }
static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4031 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.
04032 { 04033 switch (cmd) { 04034 case CLI_INIT: 04035 e->command = "jabber set debug {on|off}"; 04036 e->usage = 04037 "Usage: jabber set debug {on|off}\n" 04038 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 04039 return NULL; 04040 case CLI_GENERATE: 04041 return NULL; 04042 } 04043 04044 if (a->argc != e->args) { 04045 return CLI_SHOWUSAGE; 04046 } 04047 04048 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 04049 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04050 ASTOBJ_RDLOCK(iterator); 04051 iterator->debug = 1; 04052 ASTOBJ_UNLOCK(iterator); 04053 }); 04054 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 04055 return CLI_SUCCESS; 04056 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 04057 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04058 ASTOBJ_RDLOCK(iterator); 04059 iterator->debug = 0; 04060 ASTOBJ_UNLOCK(iterator); 04061 }); 04062 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 04063 return CLI_SUCCESS; 04064 } 04065 return CLI_SHOWUSAGE; /* defaults to invalid */ 04066 }
static int aji_filter_roster | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2942 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().
02943 { 02944 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02945 int flag = 0; 02946 iks *x = NULL; 02947 struct aji_buddy *buddy; 02948 02949 client->state = AJI_CONNECTED; 02950 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02951 ASTOBJ_RDLOCK(iterator); 02952 x = iks_child(pak->query); 02953 flag = 0; 02954 while (x) { 02955 if (!iks_strcmp(iks_name(x), "item")) { 02956 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02957 flag = 1; 02958 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02959 } 02960 } 02961 x = iks_next(x); 02962 } 02963 if (!flag) { 02964 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02965 } 02966 iks_delete(x); 02967 02968 ASTOBJ_UNLOCK(iterator); 02969 }); 02970 02971 x = iks_child(pak->query); 02972 while (x) { 02973 flag = 0; 02974 if (iks_strcmp(iks_name(x), "item") == 0) { 02975 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02976 ASTOBJ_RDLOCK(iterator); 02977 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02978 flag = 1; 02979 ASTOBJ_UNLOCK(iterator); 02980 }); 02981 02982 if (flag) { 02983 /* found buddy, don't create a new one */ 02984 x = iks_next(x); 02985 continue; 02986 } 02987 02988 buddy = ast_calloc(1, sizeof(*buddy)); 02989 if (!buddy) { 02990 ast_log(LOG_WARNING, "Out of memory\n"); 02991 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02992 return 0; 02993 } 02994 ASTOBJ_INIT(buddy); 02995 ASTOBJ_WRLOCK(buddy); 02996 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02997 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02998 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02999 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 03000 ASTOBJ_MARK(buddy); 03001 } else if (ast_test_flag(&client->flags, AJI_AUTOREGISTER)) { 03002 if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 03003 /* subscribe to buddy's presence only 03004 if we really need to */ 03005 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 03006 } 03007 } 03008 ASTOBJ_UNLOCK(buddy); 03009 if (buddy) { 03010 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 03011 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 03012 } 03013 } 03014 x = iks_next(x); 03015 } 03016 03017 iks_delete(x); 03018 aji_pruneregister(client); 03019 03020 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03021 return IKS_FILTER_EAT; 03022 }
static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
char * | name | |||
) | [static] |
Definition at line 546 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().
00547 { 00548 struct aji_resource *res = NULL; 00549 if (!buddy || !name) { 00550 return res; 00551 } 00552 res = buddy->resources; 00553 while (res) { 00554 if (!strcasecmp(res->resource, name)) { 00555 break; 00556 } 00557 res = res->next; 00558 } 00559 return res; 00560 }
static struct aji_version* aji_find_version | ( | char * | node, | |
char * | version, | |||
ikspak * | pak | |||
) | [static] |
Definition at line 474 of file res_jabber.c.
References ast_copy_string(), ast_free, ast_log(), ast_malloc, capabilities, LOG_ERROR, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::version, and aji_capabilities::versions.
Referenced by aji_handle_presence().
00475 { 00476 struct aji_capabilities *list = NULL; 00477 struct aji_version *res = NULL; 00478 00479 list = capabilities; 00480 00481 if (!node) { 00482 node = pak->from->full; 00483 } 00484 if (!version) { 00485 version = "none supplied."; 00486 } 00487 while (list) { 00488 if (!strcasecmp(list->node, node)) { 00489 res = list->versions; 00490 while(res) { 00491 if (!strcasecmp(res->version, version)) { 00492 return res; 00493 } 00494 res = res->next; 00495 } 00496 /* Specified version not found. Let's add it to 00497 this node in our capabilities list */ 00498 if (!res) { 00499 res = ast_malloc(sizeof(*res)); 00500 if (!res) { 00501 ast_log(LOG_ERROR, "Out of memory!\n"); 00502 return NULL; 00503 } 00504 res->jingle = 0; 00505 res->parent = list; 00506 ast_copy_string(res->version, version, sizeof(res->version)); 00507 res->next = list->versions; 00508 list->versions = res; 00509 return res; 00510 } 00511 } 00512 list = list->next; 00513 } 00514 /* Specified node not found. Let's add it our capabilities list */ 00515 if (!list) { 00516 list = ast_malloc(sizeof(*list)); 00517 if (!list) { 00518 ast_log(LOG_ERROR, "Out of memory!\n"); 00519 return NULL; 00520 } 00521 res = ast_malloc(sizeof(*res)); 00522 if (!res) { 00523 ast_log(LOG_ERROR, "Out of memory!\n"); 00524 ast_free(list); 00525 return NULL; 00526 } 00527 ast_copy_string(list->node, node, sizeof(list->node)); 00528 ast_copy_string(res->version, version, sizeof(res->version)); 00529 res->jingle = 0; 00530 res->parent = list; 00531 res->next = NULL; 00532 list->versions = res; 00533 list->next = capabilities; 00534 capabilities = list; 00535 } 00536 return res; 00537 }
static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Definition at line 3056 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().
03057 { 03058 iks *roster = NULL; 03059 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 03060 03061 if (roster) { 03062 iks_insert_attrib(roster, "id", "roster"); 03063 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 03064 ast_aji_send(client, roster); 03065 } 03066 03067 iks_delete(roster); 03068 03069 return 1; 03070 }
static void aji_handle_iq | ( | struct aji_client * | client, | |
iks * | node | |||
) | [static] |
static void aji_handle_message | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2227 of file res_jabber.c.
References ast_calloc, ast_cond_broadcast, ast_copy_string(), ast_debug, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvnow(), delete_old_messages(), aji_message::list, LOG_ERROR, messagelock, aji_client::messages, and aji_client::name.
Referenced by aji_act_hook().
02228 { 02229 struct aji_message *insert; 02230 int deleted = 0; 02231 02232 ast_debug(3, "client %s received a message\n", client->name); 02233 02234 if (!(insert = ast_calloc(1, sizeof(*insert)))) { 02235 return; 02236 } 02237 02238 insert->arrived = ast_tvnow(); 02239 02240 /* wake up threads waiting for messages */ 02241 ast_mutex_lock(&messagelock); 02242 ast_cond_broadcast(&message_received_condition); 02243 ast_mutex_unlock(&messagelock); 02244 02245 if (iks_find_cdata(pak->x, "body")) { 02246 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 02247 } 02248 if (pak->id) { 02249 ast_copy_string(insert->id, pak->id, sizeof(insert->id)); 02250 } 02251 if (pak->from){ 02252 /* insert will furtherly be added to message list */ 02253 insert->from = ast_strdup(pak->from->full); 02254 if (!insert->from) { 02255 ast_log(LOG_ERROR, "Memory allocation failure\n"); 02256 return; 02257 } 02258 ast_debug(3, "message comes from %s\n", insert->from); 02259 } 02260 02261 /* remove old messages received from this JID 02262 * and insert received message */ 02263 deleted = delete_old_messages(client, pak->from->partial); 02264 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 02265 AST_LIST_LOCK(&client->messages); 02266 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 02267 AST_LIST_UNLOCK(&client->messages); 02268 }
static void aji_handle_presence | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2276 of file res_jabber.c.
References AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_buddy_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_strdup, ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, descrip, aji_resource::description, EVENT_FLAG_USER, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, manager_event, aji_client::mid, aji_client::name, aji_resource::next, aji_resource::priority, aji_resource::resource, aji_buddy::resources, S_OR, aji_client::state, aji_resource::status, aji_client::status, status, and type.
Referenced by aji_act_hook().
02277 { 02278 int status, priority; 02279 struct aji_buddy *buddy; 02280 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02281 char *ver, *node, *descrip, *type; 02282 02283 if (client->state != AJI_CONNECTED) 02284 aji_create_buddy(pak->from->partial, client); 02285 02286 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02287 if (!buddy && pak->from->partial) { 02288 /* allow our jid to be used to log in with another resource */ 02289 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02290 aji_create_buddy(pak->from->partial, client); 02291 else 02292 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02293 return; 02294 } 02295 type = iks_find_attrib(pak->x, "type"); 02296 if (client->component && type &&!strcasecmp("probe", type)) { 02297 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02298 ast_verbose("what i was looking for \n"); 02299 } 02300 ASTOBJ_WRLOCK(buddy); 02301 status = (pak->show) ? pak->show : 6; 02302 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02303 tmp = buddy->resources; 02304 descrip = ast_strdup(iks_find_cdata(pak->x, "status")); 02305 02306 while (tmp && pak->from->resource) { 02307 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02308 tmp->status = status; 02309 if (tmp->description) { 02310 ast_free(tmp->description); 02311 } 02312 tmp->description = descrip; 02313 found = tmp; 02314 if (status == 6) { /* Sign off Destroy resource */ 02315 if (last && found->next) { 02316 last->next = found->next; 02317 } else if (!last) { 02318 if (found->next) { 02319 buddy->resources = found->next; 02320 } else { 02321 buddy->resources = NULL; 02322 } 02323 } else if (!found->next) { 02324 if (last) { 02325 last->next = NULL; 02326 } else { 02327 buddy->resources = NULL; 02328 } 02329 } 02330 ast_free(found); 02331 found = NULL; 02332 break; 02333 } 02334 /* resource list is sorted by descending priority */ 02335 if (tmp->priority != priority) { 02336 found->priority = priority; 02337 if (!last && !found->next) { 02338 /* resource was found to be unique, 02339 leave loop */ 02340 break; 02341 } 02342 /* search for resource in our list 02343 and take it out for the moment */ 02344 if (last) { 02345 last->next = found->next; 02346 } else { 02347 buddy->resources = found->next; 02348 } 02349 02350 last = NULL; 02351 tmp = buddy->resources; 02352 if (!buddy->resources) { 02353 buddy->resources = found; 02354 } 02355 /* priority processing */ 02356 while (tmp) { 02357 /* insert resource back according to 02358 its priority value */ 02359 if (found->priority > tmp->priority) { 02360 if (last) { 02361 /* insert within list */ 02362 last->next = found; 02363 } 02364 found->next = tmp; 02365 if (!last) { 02366 /* insert on top */ 02367 buddy->resources = found; 02368 } 02369 break; 02370 } 02371 if (!tmp->next) { 02372 /* insert at the end of the list */ 02373 tmp->next = found; 02374 found->next = NULL; 02375 break; 02376 } 02377 last = tmp; 02378 tmp = tmp->next; 02379 } 02380 } 02381 break; 02382 } 02383 last = tmp; 02384 tmp = tmp->next; 02385 } 02386 02387 /* resource not found in our list, create it */ 02388 if (!found && status != 6 && pak->from->resource) { 02389 found = ast_calloc(1, sizeof(*found)); 02390 02391 if (!found) { 02392 ast_log(LOG_ERROR, "Out of memory!\n"); 02393 ASTOBJ_UNLOCK(buddy); 02394 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02395 return; 02396 } 02397 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02398 found->status = status; 02399 found->description = descrip; 02400 found->priority = priority; 02401 found->next = NULL; 02402 last = NULL; 02403 tmp = buddy->resources; 02404 while (tmp) { 02405 if (found->priority > tmp->priority) { 02406 if (last) { 02407 last->next = found; 02408 } 02409 found->next = tmp; 02410 if (!last) { 02411 buddy->resources = found; 02412 } 02413 break; 02414 } 02415 if (!tmp->next) { 02416 tmp->next = found; 02417 break; 02418 } 02419 last = tmp; 02420 tmp = tmp->next; 02421 } 02422 if (!tmp) { 02423 buddy->resources = found; 02424 } 02425 } 02426 02427 ASTOBJ_UNLOCK(buddy); 02428 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02429 02430 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02431 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02432 02433 /* handle gmail client's special caps:c tag */ 02434 if (!node && !ver) { 02435 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02436 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02437 } 02438 02439 /* retrieve capabilites of the new resource */ 02440 if (status != 6 && found && !found->cap) { 02441 found->cap = aji_find_version(node, ver, pak); 02442 if (gtalk_yuck(pak->x)) { /* gtalk should do discover */ 02443 found->cap->jingle = 1; 02444 } 02445 if (found->cap->jingle) { 02446 ast_debug(1, "Special case for google till they support discover.\n"); 02447 } else { 02448 iks *iq, *query; 02449 iq = iks_new("iq"); 02450 query = iks_new("query"); 02451 if (query && iq) { 02452 iks_insert_attrib(iq, "type", "get"); 02453 iks_insert_attrib(iq, "to", pak->from->full); 02454 iks_insert_attrib(iq, "from", client->jid->full); 02455 iks_insert_attrib(iq, "id", client->mid); 02456 ast_aji_increment_mid(client->mid); 02457 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02458 iks_insert_node(iq, query); 02459 ast_aji_send(client, iq); 02460 } else { 02461 ast_log(LOG_ERROR, "Out of memory.\n"); 02462 } 02463 iks_delete(query); 02464 iks_delete(iq); 02465 } 02466 } 02467 switch (pak->subtype) { 02468 case IKS_TYPE_AVAILABLE: 02469 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 02470 break; 02471 case IKS_TYPE_UNAVAILABLE: 02472 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 02473 break; 02474 default: 02475 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 02476 } 02477 switch (pak->show) { 02478 case IKS_SHOW_UNAVAILABLE: 02479 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02480 break; 02481 case IKS_SHOW_AVAILABLE: 02482 ast_debug(3, "JABBER: type is available\n"); 02483 break; 02484 case IKS_SHOW_CHAT: 02485 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02486 break; 02487 case IKS_SHOW_AWAY: 02488 ast_debug(3, "JABBER: type is away\n"); 02489 break; 02490 case IKS_SHOW_XA: 02491 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02492 break; 02493 case IKS_SHOW_DND: 02494 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02495 break; 02496 default: 02497 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 02498 } 02499 02500 if (found) { 02501 manager_event(EVENT_FLAG_USER, "JabberStatus", 02502 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 02503 "\r\nDescription: %s\r\n", 02504 client->name, pak->from->partial, found->resource, found->status, 02505 found->priority, S_OR(found->description, "")); 02506 } else { 02507 manager_event(EVENT_FLAG_USER, "JabberStatus", 02508 "Account: %s\r\nJID: %s\r\nStatus: %d\r\n", 02509 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE); 02510 } 02511 }
static int aji_handle_pubsub_error | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3461 of file res_jabber.c.
References aji_create_pubsub_collection(), aji_create_pubsub_leaf(), aji_create_pubsub_node(), aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_client_destroy(), ast_aji_send(), ast_log(), ast_test_flag, ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, and pubsubflags.
Referenced by aji_init_event_distribution().
03462 { 03463 char *node_name; 03464 char *error; 03465 int error_num; 03466 iks *orig_request; 03467 iks *orig_pubsub = iks_find(pak->x, "pubsub"); 03468 struct aji_client *client; 03469 if (!orig_pubsub) { 03470 ast_log(LOG_ERROR, "Error isn't a PubSub error, why are we here?\n"); 03471 return IKS_FILTER_EAT; 03472 } 03473 orig_request = iks_child(orig_pubsub); 03474 error = iks_find_attrib(iks_find(pak->x, "error"), "code"); 03475 node_name = iks_find_attrib(orig_request, "node"); 03476 if (!sscanf(error, "%30d", &error_num)) { 03477 return IKS_FILTER_EAT; 03478 } 03479 if (error_num > 399 && error_num < 500 && error_num != 404) { 03480 ast_log(LOG_ERROR, 03481 "Error performing operation on PubSub node %s, %s.\n", node_name, error); 03482 return IKS_FILTER_EAT; 03483 } else if (error_num > 499 && error_num < 600) { 03484 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error); 03485 return IKS_FILTER_EAT; 03486 } 03487 03488 client = ASTOBJ_REF((struct aji_client *) data); 03489 03490 if (!strcasecmp(iks_name(orig_request), "publish")) { 03491 iks *request; 03492 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03493 if (iks_find(iks_find(orig_request, "item"), "state")) { 03494 aji_create_pubsub_leaf(client, "device_state", node_name); 03495 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) { 03496 aji_create_pubsub_leaf(client, "message_waiting", node_name); 03497 } 03498 } else { 03499 aji_create_pubsub_node(client, NULL, node_name, NULL); 03500 } 03501 request = aji_pubsub_iq_create(client, "set"); 03502 iks_insert_node(request, orig_pubsub); 03503 ast_aji_send(client, request); 03504 iks_delete(request); 03505 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03506 return IKS_FILTER_EAT; 03507 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) { 03508 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03509 aji_create_pubsub_collection(client, node_name); 03510 } else { 03511 aji_create_pubsub_node(client, NULL, node_name, NULL); 03512 } 03513 } 03514 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03515 return IKS_FILTER_EAT; 03516 }
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 3251 of file res_jabber.c.
References ast_devstate_val(), ast_eid_cmp(), ast_eid_default, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_RAW, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_log(), ast_str_to_eid(), context, LOG_DEBUG, LOG_ERROR, and strsep().
Referenced by aji_init_event_distribution().
03252 { 03253 char *item_id, *device_state, *context; 03254 int oldmsgs, newmsgs; 03255 iks *item, *item_content; 03256 struct ast_eid pubsub_eid; 03257 struct ast_event *event; 03258 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); 03259 if (!item) { 03260 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); 03261 return IKS_FILTER_EAT; 03262 } 03263 item_id = iks_find_attrib(item, "id"); 03264 item_content = iks_child(item); 03265 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid")); 03266 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) { 03267 ast_log(LOG_DEBUG, "Returning here, eid of incoming event matches ours!\n"); 03268 return IKS_FILTER_EAT; 03269 } 03270 if (!strcasecmp(iks_name(item_content), "state")) { 03271 device_state = iks_find_cdata(item, "state"); 03272 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, 03273 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, 03274 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, 03275 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03276 AST_EVENT_IE_END))) { 03277 return IKS_FILTER_EAT; 03278 } 03279 } else if (!strcasecmp(iks_name(item_content), "mailbox")) { 03280 context = strsep(&item_id, "@"); 03281 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs); 03282 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs); 03283 if (!(event = ast_event_new(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX, 03284 AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_CONTEXT, 03285 AST_EVENT_IE_PLTYPE_STR, context, AST_EVENT_IE_OLDMSGS, 03286 AST_EVENT_IE_PLTYPE_UINT, oldmsgs, AST_EVENT_IE_NEWMSGS, 03287 AST_EVENT_IE_PLTYPE_UINT, newmsgs, AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, 03288 &pubsub_eid, sizeof(pubsub_eid), AST_EVENT_IE_END))) { 03289 return IKS_FILTER_EAT; 03290 } 03291 } else { 03292 ast_log(LOG_DEBUG, "Don't know how to handle PubSub event of type %s\n", 03293 iks_name(item_content)); 03294 return IKS_FILTER_EAT; 03295 } 03296 ast_event_queue_and_cache(event); 03297 return IKS_FILTER_EAT; 03298 }
static void aji_handle_subscribe | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2520 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().
02521 { 02522 iks *presence = NULL, *status = NULL; 02523 struct aji_buddy* buddy = NULL; 02524 02525 switch (pak->subtype) { 02526 case IKS_TYPE_SUBSCRIBE: 02527 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) { 02528 presence = iks_new("presence"); 02529 status = iks_new("status"); 02530 if (presence && status) { 02531 iks_insert_attrib(presence, "type", "subscribed"); 02532 iks_insert_attrib(presence, "to", pak->from->full); 02533 iks_insert_attrib(presence, "from", client->jid->full); 02534 if (pak->id) 02535 iks_insert_attrib(presence, "id", pak->id); 02536 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02537 iks_insert_node(presence, status); 02538 ast_aji_send(client, presence); 02539 } else { 02540 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02541 } 02542 02543 iks_delete(presence); 02544 iks_delete(status); 02545 } 02546 02547 if (client->component) 02548 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02549 case IKS_TYPE_SUBSCRIBED: 02550 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02551 if (!buddy && pak->from->partial) { 02552 aji_create_buddy(pak->from->partial, client); 02553 } else if (buddy) { 02554 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02555 } 02556 default: 02557 if (option_verbose > 4) { 02558 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 02559 } 02560 } 02561 }
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 3222 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(), device_state_sub, aji_client::f, mwi_sub, and aji_client::pubsub_node.
Referenced by aji_client_connect(), and aji_reload().
03223 { 03224 if (!mwi_sub) { 03225 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription", 03226 client, AST_EVENT_IE_END); 03227 } 03228 if (!device_state_sub) { 03229 if (ast_enable_distributed_devstate()) { 03230 return; 03231 } 03232 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 03233 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END); 03234 ast_event_dump_cache(device_state_sub); 03235 } 03236 03237 aji_pubsub_subscribe(client, "device_state"); 03238 aji_pubsub_subscribe(client, "message_waiting"); 03239 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE, 03240 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE); 03241 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE, 03242 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE); 03243 03244 }
static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 3114 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().
03115 { 03116 int connected = IKS_NET_NOCONN; 03117 03118 #ifdef HAVE_OPENSSL 03119 /* reset stream flags */ 03120 client->stream_flags = 0; 03121 #endif 03122 /* If it's a component, connect to user, otherwise, connect to server */ 03123 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 03124 03125 if (connected == IKS_NET_NOCONN) { 03126 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 03127 return IKS_HOOK; 03128 } else if (connected == IKS_NET_NODNS) { 03129 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, 03130 S_OR(client->serverhost, client->jid->server)); 03131 return IKS_HOOK; 03132 } 03133 03134 return IKS_OK; 03135 }
static int aji_io_recv | ( | struct aji_client * | client, | |
char * | buffer, | |||
size_t | buf_len, | |||
int | timeout | |||
) | [static] |
Definition at line 1296 of file res_jabber.c.
References aji_is_secure(), ast_poll, len(), aji_client::p, and aji_client::ssl_session.
Referenced by aji_recv().
01297 { 01298 struct pollfd pfd = { .events = POLLIN }; 01299 int len, res; 01300 01301 #ifdef HAVE_OPENSSL 01302 if (aji_is_secure(client)) { 01303 pfd.fd = SSL_get_fd(client->ssl_session); 01304 if (pfd.fd < 0) { 01305 return -1; 01306 } 01307 } else 01308 #endif /* HAVE_OPENSSL */ 01309 pfd.fd = iks_fd(client->p); 01310 01311 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1); 01312 if (res > 0) { 01313 #ifdef HAVE_OPENSSL 01314 if (aji_is_secure(client)) { 01315 len = SSL_read(client->ssl_session, buffer, buf_len); 01316 } else 01317 #endif /* HAVE_OPENSSL */ 01318 len = recv(pfd.fd, buffer, buf_len, 0); 01319 01320 if (len > 0) { 01321 return len; 01322 } else if (len <= 0) { 01323 return -1; 01324 } 01325 } 01326 return res; 01327 }
static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Definition at line 1206 of file res_jabber.c.
References aji_client::stream_flags.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
01207 { 01208 #ifdef HAVE_OPENSSL 01209 return client->stream_flags & SECURE; 01210 #else 01211 return 0; 01212 #endif 01213 }
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 991 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().
00992 { 00993 struct aji_client *client = NULL; 00994 char *s; 00995 char nick[AJI_MAX_RESJIDLEN]; 00996 00997 AST_DECLARE_APP_ARGS(args, 00998 AST_APP_ARG(sender); 00999 AST_APP_ARG(jid); 01000 AST_APP_ARG(nick); 01001 ); 01002 01003 if (!data) { 01004 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01005 return -1; 01006 } 01007 s = ast_strdupa(data); 01008 01009 AST_STANDARD_APP_ARGS(args, s); 01010 if (args.argc < 2 || args.argc > 3) { 01011 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01012 return -1; 01013 } 01014 01015 if (strchr(args.jid, '/')) { 01016 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n"); 01017 return -1; 01018 } 01019 01020 if (!(client = ast_aji_get_client(args.sender))) { 01021 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01022 return -1; 01023 } 01024 01025 if (!ast_strlen_zero(args.nick)) { 01026 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01027 } else { 01028 if (client->component) { 01029 sprintf(nick, "asterisk"); 01030 } else { 01031 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01032 } 01033 } 01034 01035 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01036 ast_aji_join_chat(client, args.jid, nick); 01037 } else { 01038 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid); 01039 } 01040 01041 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01042 return 0; 01043 }
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 1052 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().
01053 { 01054 struct aji_client *client = NULL; 01055 char *s; 01056 char nick[AJI_MAX_RESJIDLEN]; 01057 AST_DECLARE_APP_ARGS(args, 01058 AST_APP_ARG(sender); 01059 AST_APP_ARG(jid); 01060 AST_APP_ARG(nick); 01061 ); 01062 01063 if (!data) { 01064 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01065 return -1; 01066 } 01067 s = ast_strdupa(data); 01068 01069 AST_STANDARD_APP_ARGS(args, s); 01070 if (args.argc < 2 || args.argc > 3) { 01071 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01072 return -1; 01073 } 01074 01075 if (strchr(args.jid, '/')) { 01076 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n"); 01077 return -1; 01078 } 01079 01080 if (!(client = ast_aji_get_client(args.sender))) { 01081 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01082 return -1; 01083 } 01084 01085 if (!ast_strlen_zero(args.nick)) { 01086 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01087 } else { 01088 if (client->component) { 01089 sprintf(nick, "asterisk"); 01090 } else { 01091 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01092 } 01093 } 01094 01095 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01096 ast_aji_leave_chat(client, args.jid, nick); 01097 } 01098 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01099 return 0; 01100 }
static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 4537 of file res_jabber.c.
References AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, ast_category_browse(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, debug, globalflags, JABBER_CONFIG, LOG_WARNING, and var.
Referenced by aji_reload().
04538 { 04539 char *cat = NULL; 04540 int debug = 0; 04541 struct ast_config *cfg = NULL; 04542 struct ast_variable *var = NULL; 04543 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04544 04545 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 04546 return -1; 04547 } 04548 04549 /* Reset flags to default value */ 04550 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT); 04551 04552 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 04553 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 04554 return 0; 04555 } 04556 04557 cat = ast_category_browse(cfg, NULL); 04558 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 04559 if (!strcasecmp(var->name, "debug")) { 04560 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 04561 } else if (!strcasecmp(var->name, "autoprune")) { 04562 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 04563 } else if (!strcasecmp(var->name, "autoregister")) { 04564 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 04565 } else if (!strcasecmp(var->name, "collection_nodes")) { 04566 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248); 04567 } else if (!strcasecmp(var->name, "pubsub_autocreate")) { 04568 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE); 04569 } else if (!strcasecmp(var->name, "auth_policy")) { 04570 if (!strcasecmp(var->value, "accept")) { 04571 ast_set_flag(&globalflags, AJI_AUTOACCEPT); 04572 } else { 04573 ast_clear_flag(&globalflags, AJI_AUTOACCEPT); 04574 } 04575 } 04576 } 04577 04578 while (cat) { 04579 if (strcasecmp(cat, "general")) { 04580 var = ast_variable_browse(cfg, cat); 04581 aji_create_client(cat, var, debug); 04582 } 04583 cat = ast_category_browse(cfg, cat); 04584 } 04585 ast_config_destroy(cfg); /* or leak memory */ 04586 return 1; 04587 }
static void aji_log_hook | ( | void * | data, | |
const char * | xmpp, | |||
size_t | size, | |||
int | is_incoming | |||
) | [static] |
Definition at line 1487 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().
01488 { 01489 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01490 01491 if (!ast_strlen_zero(xmpp)) { 01492 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 01493 } 01494 01495 if (client->debug) { 01496 if (is_incoming) { 01497 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 01498 } else { 01499 if (strlen(xmpp) == 1) { 01500 if (option_debug > 2 && xmpp[0] == ' ') { 01501 ast_verbose("\nJABBER: Keep alive packet\n"); 01502 } 01503 } else { 01504 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 01505 } 01506 } 01507 01508 } 01509 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01510 }
static void aji_message_destroy | ( | struct aji_message * | obj | ) | [static] |
Definition at line 453 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().
00454 { 00455 if (obj->from) { 00456 ast_free(obj->from); 00457 } 00458 if (obj->message) { 00459 ast_free(obj->message); 00460 } 00461 ast_free(obj); 00462 }
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 3167 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().
03168 { 03169 const char *mailbox; 03170 const char *context; 03171 char oldmsgs[10]; 03172 char newmsgs[10]; 03173 struct aji_client *client; 03174 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03175 { 03176 /* If the event didn't originate from this server, don't send it back out. */ 03177 ast_log(LOG_DEBUG, "Returning here\n"); 03178 return; 03179 } 03180 03181 client = ASTOBJ_REF((struct aji_client *) data); 03182 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX); 03183 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT); 03184 snprintf(oldmsgs, sizeof(oldmsgs), "%d", 03185 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS)); 03186 snprintf(newmsgs, sizeof(newmsgs), "%d", 03187 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS)); 03188 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs); 03189 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03190 03191 }
static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2888 of file res_jabber.c.
References AJI_AUTOPRUNE, ast_aji_send(), ast_log(), ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, aji_client::buddies, and LOG_ERROR.
02889 { 02890 iks *removeiq = iks_new("iq"); 02891 iks *removequery = iks_new("query"); 02892 iks *removeitem = iks_new("item"); 02893 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02894 if (!client || !removeiq || !removequery || !removeitem || !send) { 02895 ast_log(LOG_ERROR, "Out of memory.\n"); 02896 goto safeout; 02897 } 02898 02899 iks_insert_node(removeiq, removequery); 02900 iks_insert_node(removequery, removeitem); 02901 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02902 ASTOBJ_RDLOCK(iterator); 02903 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02904 * be called at the same time */ 02905 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02906 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02907 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02908 " so I am no longer subscribing to your presence.\n")); 02909 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02910 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02911 " your access to my presence.\n")); 02912 iks_insert_attrib(removeiq, "from", client->jid->full); 02913 iks_insert_attrib(removeiq, "type", "set"); 02914 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02915 iks_insert_attrib(removeitem, "jid", iterator->name); 02916 iks_insert_attrib(removeitem, "subscription", "remove"); 02917 ast_aji_send(client, removeiq); 02918 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02919 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02920 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02921 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02922 } 02923 ASTOBJ_UNLOCK(iterator); 02924 }); 02925 02926 safeout: 02927 iks_delete(removeiq); 02928 iks_delete(removequery); 02929 iks_delete(removeitem); 02930 iks_delete(send); 02931 02932 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, ast_aji_buddy_destroy); 02933 }
static void aji_publish_device_state | ( | struct aji_client * | client, | |
const char * | device, | |||
const char * | device_state | |||
) | [static] |
Publish device state to a PubSub node.
client | the configured XMPP client we use to connect to a XMPP server | |
device | the name of the device whose state to publish | |
device_state | the state to publish |
Definition at line 3396 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(), ast_test_flag, and pubsubflags.
Referenced by aji_devstate_cb().
03398 { 03399 iks *request = aji_build_publish_skeleton(client, device, "device_state"); 03400 iks *state; 03401 char eid_str[20]; 03402 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { 03403 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03404 aji_create_pubsub_node(client, "leaf", device, "device_state"); 03405 } else { 03406 aji_create_pubsub_node(client, NULL, device, NULL); 03407 } 03408 } 03409 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03410 state = iks_insert(request, "state"); 03411 iks_insert_attrib(state, "xmlns", "http://asterisk.org"); 03412 iks_insert_attrib(state, "eid", eid_str); 03413 iks_insert_cdata(state, device_state, strlen(device_state)); 03414 ast_aji_send(client, iks_root(request)); 03415 iks_delete(request); 03416 }
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 3425 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().
03427 { 03428 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT]; 03429 char eid_str[20]; 03430 iks *mailbox_node, *request; 03431 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); 03432 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting"); 03433 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03434 mailbox_node = iks_insert(request, "mailbox"); 03435 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org"); 03436 iks_insert_attrib(mailbox_node, "eid", eid_str); 03437 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs)); 03438 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs)); 03439 ast_aji_send(client, iks_root(request)); 03440 iks_delete(request); 03441 }
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 3449 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().
03450 { 03451 iks *request = iks_new("iq"); 03452 03453 iks_insert_attrib(request, "to", client->pubsub_node); 03454 iks_insert_attrib(request, "from", client->jid->full); 03455 iks_insert_attrib(request, "type", type); 03456 ast_aji_increment_mid(client->mid); 03457 iks_insert_attrib(request, "id", client->mid); 03458 return request; 03459 }
static void aji_pubsub_purge_nodes | ( | struct aji_client * | client, | |
const char * | collection_name | |||
) | [static] |
Definition at line 3669 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().
03670 { 03671 iks *request = aji_build_node_request(client, collection_name); 03672 ast_aji_send(client, request); 03673 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE, 03674 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03675 IKS_RULE_DONE); 03676 ast_aji_send(client, request); 03677 iks_delete(request); 03678 }
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 3331 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_send(), ast_test_flag, globalflags, and aji_client::jid.
Referenced by aji_init_event_distribution().
03332 { 03333 iks *request = aji_pubsub_iq_create(client, "set"); 03334 iks *pubsub, *subscribe; 03335 03336 pubsub = iks_insert(request, "pubsub"); 03337 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03338 subscribe = iks_insert(pubsub, "subscribe"); 03339 iks_insert_attrib(subscribe, "jid", client->jid->partial); 03340 iks_insert_attrib(subscribe, "node", node); 03341 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03342 iks *options, *x, *sub_options, *sub_type, *sub_depth; 03343 options = iks_insert(pubsub, "options"); 03344 x = iks_insert(options, "x"); 03345 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03346 iks_insert_attrib(x, "type", "submit"); 03347 sub_options = iks_insert(x, "field"); 03348 iks_insert_attrib(sub_options, "var", "FORM_TYPE"); 03349 iks_insert_attrib(sub_options, "type", "hidden"); 03350 iks_insert_cdata(iks_insert(sub_options, "value"), 03351 "http://jabber.org/protocol/pubsub#subscribe_options", 51); 03352 sub_type = iks_insert(x, "field"); 03353 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type"); 03354 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5); 03355 sub_depth = iks_insert(x, "field"); 03356 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth"); 03357 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3); 03358 } 03359 ast_aji_send(client, request); 03360 iks_delete(request); 03361 }
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 3560 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().
03561 { 03562 03563 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03564 iks *item = NULL; 03565 if (iks_has_children(pak->query)) { 03566 item = iks_first_tag(pak->query); 03567 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial, 03568 iks_find_attrib(item, "node")); 03569 while ((item = iks_next_tag(item))) { 03570 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node")); 03571 } 03572 } 03573 if (item) { 03574 iks_delete(item); 03575 } 03576 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03577 return IKS_FILTER_EAT; 03578 }
static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 3030 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().
03031 { 03032 int res = 0; 03033 03034 if (client->state) { 03035 client->state = AJI_DISCONNECTED; 03036 } 03037 client->timeout = 50; 03038 if (client->p) { 03039 iks_parser_reset(client->p); 03040 } 03041 if (client->authorized) { 03042 client->authorized = 0; 03043 } 03044 03045 res = aji_initialize(client); 03046 03047 return res; 03048 }
static int aji_recv | ( | struct aji_client * | client, | |
int | timeout | |||
) | [static] |
Definition at line 1341 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().
01342 { 01343 int len, ret; 01344 char buf[NET_IO_BUF_SIZE - 1]; 01345 char newbuf[NET_IO_BUF_SIZE - 1]; 01346 int pos = 0; 01347 int newbufpos = 0; 01348 unsigned char c; 01349 01350 memset(buf, 0, sizeof(buf)); 01351 memset(newbuf, 0, sizeof(newbuf)); 01352 01353 while (1) { 01354 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 01355 if (len < 0) return IKS_NET_RWERR; 01356 if (len == 0) return IKS_NET_EXPIRED; 01357 buf[len] = '\0'; 01358 01359 /* our iksemel parser won't work as expected if we feed 01360 it with XML packets that contain multiple whitespace 01361 characters between tags */ 01362 while (pos < len) { 01363 c = buf[pos]; 01364 /* if we stumble on the ending tag character, 01365 we skip any whitespace that follows it*/ 01366 if (c == '>') { 01367 while (isspace(buf[pos+1])) { 01368 pos++; 01369 } 01370 } 01371 newbuf[newbufpos] = c; 01372 newbufpos ++; 01373 pos++; 01374 } 01375 pos = 0; 01376 newbufpos = 0; 01377 01378 /* Log the message here, because iksemel's logHook is 01379 unaccessible */ 01380 aji_log_hook(client, buf, len, 1); 01381 01382 /* let iksemel deal with the string length, 01383 and reset our buffer */ 01384 ret = iks_parse(client->p, newbuf, 0, 0); 01385 memset(newbuf, 0, sizeof(newbuf)); 01386 01387 switch (ret) { 01388 case IKS_NOMEM: 01389 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 01390 break; 01391 case IKS_BADXML: 01392 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 01393 break; 01394 case IKS_HOOK: 01395 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 01396 break; 01397 } 01398 if (ret != IKS_OK) { 01399 return ret; 01400 } 01401 ast_debug(3, "XML parsing successful\n"); 01402 } 01403 return IKS_OK; 01404 }
static void * aji_recv_loop | ( | void * | data | ) | [static] |
Definition at line 2722 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().
02723 { 02724 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02725 int res = IKS_HOOK; 02726 02727 while (res != IKS_OK) { 02728 ast_debug(3, "JABBER: Connecting.\n"); 02729 res = aji_reconnect(client); 02730 sleep(4); 02731 } 02732 02733 do { 02734 if (res == IKS_NET_RWERR || client->timeout == 0) { 02735 while (res != IKS_OK) { 02736 ast_debug(3, "JABBER: reconnecting.\n"); 02737 res = aji_reconnect(client); 02738 sleep(4); 02739 } 02740 } 02741 02742 res = aji_recv(client, 1); 02743 02744 if (client->state == AJI_DISCONNECTING) { 02745 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02746 pthread_exit(NULL); 02747 } 02748 02749 /* Decrease timeout if no data received, and delete 02750 * old messages globally */ 02751 if (res == IKS_NET_EXPIRED) { 02752 client->timeout--; 02753 delete_old_messages_all(client); 02754 } 02755 if (res == IKS_HOOK) { 02756 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02757 } else if (res == IKS_NET_TLSFAIL) { 02758 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02759 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02760 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02761 if (res == IKS_OK) { 02762 client->timeout = 50; 02763 } else { 02764 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02765 } 02766 } else if (res == IKS_NET_RWERR) { 02767 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02768 } 02769 } while (client); 02770 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02771 return 0; 02772 }
static int aji_register_approve_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1792 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().
01793 { 01794 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01795 iks *iq = NULL, *presence = NULL, *x = NULL; 01796 01797 iq = iks_new("iq"); 01798 presence = iks_new("presence"); 01799 x = iks_new("x"); 01800 if (client && iq && presence && x) { 01801 if (!iks_find(pak->query, "remove")) { 01802 iks_insert_attrib(iq, "from", client->jid->full); 01803 iks_insert_attrib(iq, "to", pak->from->full); 01804 iks_insert_attrib(iq, "id", pak->id); 01805 iks_insert_attrib(iq, "type", "result"); 01806 ast_aji_send(client, iq); 01807 01808 iks_insert_attrib(presence, "from", client->jid->full); 01809 iks_insert_attrib(presence, "to", pak->from->partial); 01810 iks_insert_attrib(presence, "id", client->mid); 01811 ast_aji_increment_mid(client->mid); 01812 iks_insert_attrib(presence, "type", "subscribe"); 01813 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01814 iks_insert_node(presence, x); 01815 ast_aji_send(client, presence); 01816 } 01817 } else { 01818 ast_log(LOG_ERROR, "Out of memory.\n"); 01819 } 01820 01821 iks_delete(iq); 01822 iks_delete(presence); 01823 iks_delete(x); 01824 01825 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01826 return IKS_FILTER_EAT; 01827 }
static int aji_register_query_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1835 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().
01836 { 01837 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01838 struct aji_buddy *buddy = NULL; 01839 char *node = NULL; 01840 iks *iq = NULL, *query = NULL; 01841 01842 client = (struct aji_client *) data; 01843 01844 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01845 if (!buddy) { 01846 iks *error = NULL, *notacceptable = NULL; 01847 01848 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01849 iq = iks_new("iq"); 01850 query = iks_new("query"); 01851 error = iks_new("error"); 01852 notacceptable = iks_new("not-acceptable"); 01853 if (iq && query && error && notacceptable) { 01854 iks_insert_attrib(iq, "type", "error"); 01855 iks_insert_attrib(iq, "from", client->user); 01856 iks_insert_attrib(iq, "to", pak->from->full); 01857 iks_insert_attrib(iq, "id", pak->id); 01858 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01859 iks_insert_attrib(error, "code" , "406"); 01860 iks_insert_attrib(error, "type", "modify"); 01861 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01862 iks_insert_node(iq, query); 01863 iks_insert_node(iq, error); 01864 iks_insert_node(error, notacceptable); 01865 ast_aji_send(client, iq); 01866 } else { 01867 ast_log(LOG_ERROR, "Out of memory.\n"); 01868 } 01869 01870 iks_delete(error); 01871 iks_delete(notacceptable); 01872 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01873 iks *instructions = NULL; 01874 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01875 iq = iks_new("iq"); 01876 query = iks_new("query"); 01877 instructions = iks_new("instructions"); 01878 if (iq && query && instructions && client) { 01879 iks_insert_attrib(iq, "from", client->user); 01880 iks_insert_attrib(iq, "to", pak->from->full); 01881 iks_insert_attrib(iq, "id", pak->id); 01882 iks_insert_attrib(iq, "type", "result"); 01883 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01884 iks_insert_cdata(instructions, explain, 0); 01885 iks_insert_node(iq, query); 01886 iks_insert_node(query, instructions); 01887 ast_aji_send(client, iq); 01888 } else { 01889 ast_log(LOG_ERROR, "Out of memory.\n"); 01890 } 01891 01892 iks_delete(instructions); 01893 } 01894 iks_delete(iq); 01895 iks_delete(query); 01896 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 01897 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01898 return IKS_FILTER_EAT; 01899 }
static int aji_reload | ( | int | reload | ) | [static] |
Definition at line 4674 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, clients, and LOG_ERROR.
Referenced by aji_do_reload(), load_module(), and reload().
04675 { 04676 int res; 04677 04678 ASTOBJ_CONTAINER_MARKALL(&clients); 04679 if (!(res = aji_load_config(reload))) { 04680 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 04681 return 0; 04682 } else if (res == -1) 04683 return 1; 04684 04685 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, ast_aji_client_destroy); 04686 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04687 ASTOBJ_RDLOCK(iterator); 04688 if (iterator->state == AJI_DISCONNECTED) { 04689 if (!iterator->thread) 04690 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 04691 } else if (iterator->state == AJI_CONNECTING) { 04692 aji_get_roster(iterator); 04693 if (iterator->distribute_events) { 04694 aji_init_event_distribution(iterator); 04695 } 04696 } 04697 04698 ASTOBJ_UNLOCK(iterator); 04699 }); 04700 04701 return 1; 04702 }
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 3524 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().
03525 { 03526 iks *request = aji_build_node_request(client, collection); 03527 03528 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE, 03529 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03530 IKS_RULE_DONE); 03531 ast_aji_send(client, request); 03532 iks_delete(request); 03533 03534 }
static int aji_send_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 1110 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().
01111 { 01112 struct aji_client *client = NULL; 01113 char *s; 01114 AST_DECLARE_APP_ARGS(args, 01115 AST_APP_ARG(sender); 01116 AST_APP_ARG(recipient); 01117 AST_APP_ARG(message); 01118 ); 01119 01120 if (!data) { 01121 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01122 return -1; 01123 } 01124 s = ast_strdupa(data); 01125 01126 AST_STANDARD_APP_ARGS(args, s); 01127 if (args.argc < 3) { 01128 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01129 return -1; 01130 } 01131 01132 if (!(client = ast_aji_get_client(args.sender))) { 01133 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 01134 return -1; 01135 } 01136 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) { 01137 ast_aji_send_chat(client, args.recipient, args.message); 01138 } 01139 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01140 return 0; 01141 }
static int aji_send_header | ( | struct aji_client * | client, | |
const char * | to | |||
) | [static] |
Definition at line 1413 of file res_jabber.c.
References aji_send_raw(), len(), and aji_client::name_space.
Referenced by aji_act_hook(), and aji_tls_handshake().
01414 { 01415 char *msg; 01416 int len, err; 01417 01418 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 01419 msg = iks_malloc(len); 01420 if (!msg) 01421 return IKS_NOMEM; 01422 sprintf(msg, "<?xml version='1.0'?>" 01423 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 01424 "%s' to='%s' version='1.0'>", client->name_space, to); 01425 err = aji_send_raw(client, msg); 01426 iks_free(msg); 01427 if (err != IKS_OK) 01428 return err; 01429 01430 return IKS_OK; 01431 }
static int aji_send_raw | ( | struct aji_client * | client, | |
const char * | xmlstr | |||
) | [static] |
Definition at line 1453 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().
01454 { 01455 int ret; 01456 #ifdef HAVE_OPENSSL 01457 int len = strlen(xmlstr); 01458 01459 if (aji_is_secure(client)) { 01460 ret = SSL_write(client->ssl_session, xmlstr, len); 01461 if (ret) { 01462 /* Log the message here, because iksemel's logHook is 01463 unaccessible */ 01464 aji_log_hook(client, xmlstr, len, 0); 01465 return IKS_OK; 01466 } 01467 } 01468 #endif 01469 /* If needed, data will be sent unencrypted, and logHook will 01470 be called inside iks_send_raw */ 01471 ret = iks_send_raw(client->p, xmlstr); 01472 if (ret != IKS_OK) { 01473 return ret; 01474 } 01475 01476 return IKS_OK; 01477 }
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 2598 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().
02599 { 02600 int res = 0; 02601 iks *message_packet = NULL; 02602 char from[AJI_MAX_JIDLEN]; 02603 /* the nickname is used only in component mode */ 02604 if (nick && client->component) { 02605 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 02606 } else { 02607 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 02608 } 02609 02610 if (client->state != AJI_CONNECTED) { 02611 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02612 return -1; 02613 } 02614 02615 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message); 02616 if (!message_packet) { 02617 ast_log(LOG_ERROR, "Out of memory.\n"); 02618 return -1; 02619 } 02620 iks_insert_attrib(message_packet, "from", from); 02621 res = ast_aji_send(client, message_packet); 02622 iks_delete(message_packet); 02623 02624 return res; 02625 }
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 1150 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().
01151 { 01152 struct aji_client *client = NULL; 01153 char *s; 01154 char nick[AJI_MAX_RESJIDLEN]; 01155 int res = 0; 01156 AST_DECLARE_APP_ARGS(args, 01157 AST_APP_ARG(sender); 01158 AST_APP_ARG(groupchat); 01159 AST_APP_ARG(message); 01160 AST_APP_ARG(nick); 01161 ); 01162 01163 if (!data) { 01164 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01165 return -1; 01166 } 01167 s = ast_strdupa(data); 01168 01169 AST_STANDARD_APP_ARGS(args, s); 01170 if (args.argc < 3 || args.argc > 4) { 01171 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01172 return -1; 01173 } 01174 01175 if (!(client = ast_aji_get_client(args.sender))) { 01176 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01177 return -1; 01178 } 01179 01180 if (ast_strlen_zero(args.nick) || args.argc == 3) { 01181 if (client->component) { 01182 sprintf(nick, "asterisk"); 01183 } else { 01184 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01185 } 01186 } else { 01187 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01188 } 01189 01190 if (strchr(args.groupchat, '@') && !ast_strlen_zero(args.message)) { 01191 res = ast_aji_send_groupchat(client, nick, args.groupchat, args.message); 01192 } 01193 01194 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01195 if (res != IKS_OK) { 01196 return -1; 01197 } 01198 return 0; 01199 }
static int aji_set_group_presence | ( | struct aji_client * | client, | |
char * | room, | |||
int | level, | |||
char * | nick, | |||
char * | desc | |||
) | [static] |
Definition at line 3990 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().
03991 { 03992 int res = 0; 03993 iks *presence = NULL, *x = NULL; 03994 char from[AJI_MAX_JIDLEN]; 03995 char roomid[AJI_MAX_JIDLEN]; 03996 03997 presence = iks_make_pres(level, NULL); 03998 x = iks_new("x"); 03999 04000 if (client->component) { 04001 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 04002 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick); 04003 } else { 04004 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 04005 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user); 04006 } 04007 04008 if (!presence || !x || !client) { 04009 ast_log(LOG_ERROR, "Out of memory.\n"); 04010 res = -1; 04011 goto safeout; 04012 } else { 04013 iks_insert_attrib(presence, "to", roomid); 04014 iks_insert_attrib(presence, "from", from); 04015 iks_insert_attrib(x, "xmlns", MUC_NS); 04016 iks_insert_node(presence, x); 04017 res = ast_aji_send(client, presence); 04018 } 04019 04020 safeout: 04021 iks_delete(presence); 04022 iks_delete(x); 04023 return res; 04024 }
static void aji_set_presence | ( | struct aji_client * | client, | |
char * | to, | |||
char * | from, | |||
int | level, | |||
char * | desc | |||
) | [static] |
Definition at line 3948 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().
03949 { 03950 iks *presence = iks_make_pres(level, desc); 03951 iks *cnode = iks_new("c"); 03952 iks *priority = iks_new("priority"); 03953 char priorityS[10]; 03954 03955 if (presence && cnode && client && priority) { 03956 if (to) { 03957 iks_insert_attrib(presence, "to", to); 03958 } 03959 if (from) { 03960 iks_insert_attrib(presence, "from", from); 03961 } 03962 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 03963 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 03964 iks_insert_node(presence, priority); 03965 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 03966 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 03967 iks_insert_attrib(cnode, "ext", "voice-v1"); 03968 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 03969 iks_insert_node(presence, cnode); 03970 ast_aji_send(client, presence); 03971 } else { 03972 ast_log(LOG_ERROR, "Out of memory.\n"); 03973 } 03974 03975 iks_delete(cnode); 03976 iks_delete(presence); 03977 iks_delete(priority); 03978 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4142 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.
04143 { 04144 struct aji_resource *resource; 04145 struct aji_client *client; 04146 04147 switch (cmd) { 04148 case CLI_INIT: 04149 e->command = "jabber show buddies"; 04150 e->usage = 04151 "Usage: jabber show buddies\n" 04152 " Shows buddy lists of our clients\n"; 04153 return NULL; 04154 case CLI_GENERATE: 04155 return NULL; 04156 } 04157 04158 ast_cli(a->fd, "Jabber buddy lists\n"); 04159 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04160 ast_cli(a->fd, "Client: %s\n", iterator->user); 04161 client = iterator; 04162 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04163 ASTOBJ_RDLOCK(iterator); 04164 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name); 04165 if (!iterator->resources) 04166 ast_cli(a->fd, "\t\tResource: None\n"); 04167 for (resource = iterator->resources; resource; resource = resource->next) { 04168 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource); 04169 if (resource->cap) { 04170 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node); 04171 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version); 04172 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 04173 } 04174 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status); 04175 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority); 04176 } 04177 ASTOBJ_UNLOCK(iterator); 04178 }); 04179 iterator = client; 04180 }); 04181 return CLI_SUCCESS; 04182 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4096 of file res_jabber.c.
References AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, clients, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.
04097 { 04098 char *status; 04099 int count = 0; 04100 04101 switch (cmd) { 04102 case CLI_INIT: 04103 e->command = "jabber show connections"; 04104 e->usage = 04105 "Usage: jabber show connections\n" 04106 " Shows state of client and component connections\n"; 04107 return NULL; 04108 case CLI_GENERATE: 04109 return NULL; 04110 } 04111 04112 ast_cli(a->fd, "Jabber Users and their status:\n"); 04113 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04114 ASTOBJ_RDLOCK(iterator); 04115 count++; 04116 switch (iterator->state) { 04117 case AJI_DISCONNECTED: 04118 status = "Disconnected"; 04119 break; 04120 case AJI_CONNECTING: 04121 status = "Connecting"; 04122 break; 04123 case AJI_CONNECTED: 04124 status = "Connected"; 04125 break; 04126 default: 04127 status = "Unknown"; 04128 } 04129 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status); 04130 ASTOBJ_UNLOCK(iterator); 04131 }); 04132 ast_cli(a->fd, "----\n"); 04133 ast_cli(a->fd, " Number of users: %d\n", count); 04134 return CLI_SUCCESS; 04135 }
static int aji_start_sasl | ( | struct aji_client * | client, | |
enum ikssasltype | type, | |||
char * | username, | |||
char * | pass | |||
) | [static] |
Definition at line 1522 of file res_jabber.c.
References aji_is_secure(), ast_aji_send(), ast_base64encode(), ast_log(), base64, len(), LOG_ERROR, and aji_client::p.
Referenced by aji_act_hook().
01523 { 01524 iks *x = NULL; 01525 int len; 01526 char *s; 01527 char *base64; 01528 01529 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 01530 iks_start_sasl is an iksemel API function and relies on GnuTLS, 01531 whereas we use OpenSSL */ 01532 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 01533 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 01534 if (!(type & IKS_STREAM_SASL_PLAIN)) { 01535 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 01536 return IKS_NET_NOTSUPP; 01537 } 01538 01539 x = iks_new("auth"); 01540 if (!x) { 01541 ast_log(LOG_ERROR, "Out of memory.\n"); 01542 return IKS_NET_NOTSUPP; 01543 } 01544 01545 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 01546 len = strlen(username) + strlen(pass) + 3; 01547 s = alloca(len); 01548 base64 = alloca((len + 2) * 4 / 3); 01549 iks_insert_attrib(x, "mechanism", "PLAIN"); 01550 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 01551 01552 /* exclude the NULL training byte from the base64 encoding operation 01553 as some XMPP servers will refuse it. 01554 The format for authentication is [authzid]\0authcid\0password 01555 not [authzid]\0authcid\0password\0 */ 01556 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 01557 iks_insert_cdata(x, base64, 0); 01558 ast_aji_send(client, x); 01559 iks_delete(x); 01560 01561 return IKS_OK; 01562 }
static int aji_start_tls | ( | struct aji_client * | client | ) | [static] |
Definition at line 1223 of file res_jabber.c.
References aji_client::p, and aji_client::stream_flags.
Referenced by aji_act_hook().
01224 { 01225 int ret; 01226 01227 /* This is sent not encrypted */ 01228 if ((ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"))) { 01229 return ret; 01230 } 01231 01232 client->stream_flags |= TRY_SECURE; 01233 return IKS_OK; 01234 }
static int aji_status_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 622 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().
00623 { 00624 struct aji_client *client = NULL; 00625 struct aji_buddy *buddy = NULL; 00626 struct aji_resource *r = NULL; 00627 char *s = NULL; 00628 int stat = 7; 00629 char status[2]; 00630 static int deprecation_warning = 0; 00631 AST_DECLARE_APP_ARGS(args, 00632 AST_APP_ARG(sender); 00633 AST_APP_ARG(jid); 00634 AST_APP_ARG(variable); 00635 ); 00636 AST_DECLARE_APP_ARGS(jid, 00637 AST_APP_ARG(screenname); 00638 AST_APP_ARG(resource); 00639 ); 00640 00641 if (deprecation_warning++ % 10 == 0) { 00642 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00643 } 00644 00645 if (!data) { 00646 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00647 return 0; 00648 } 00649 s = ast_strdupa(data); 00650 AST_STANDARD_APP_ARGS(args, s); 00651 00652 if (args.argc != 3) { 00653 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00654 return -1; 00655 } 00656 00657 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00658 if (jid.argc < 1 || jid.argc > 2) { 00659 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00660 return -1; 00661 } 00662 00663 if (!(client = ast_aji_get_client(args.sender))) { 00664 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00665 return -1; 00666 } 00667 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00668 if (!buddy) { 00669 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00670 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00671 return -1; 00672 } 00673 r = aji_find_resource(buddy, jid.resource); 00674 if (!r && buddy->resources) { 00675 r = buddy->resources; 00676 } 00677 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00678 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00679 if (!r) { 00680 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00681 } else { 00682 stat = r->status; 00683 } 00684 snprintf(status, sizeof(status), "%d", stat); 00685 pbx_builtin_setvar_helper(chan, args.variable, status); 00686 return 0; 00687 }
static char * aji_test | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4189 of file res_jabber.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_aji_send_chat(), ast_cli(), ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, aji_client::buddies, aji_resource::cap, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, clients, ast_cli_entry::command, aji_resource::description, ast_cli_args::fd, aji_version::jingle, name, aji_resource::next, aji_capabilities::node, aji_version::parent, aji_resource::priority, aji_resource::resource, S_OR, aji_resource::status, ast_cli_entry::usage, and aji_version::version.
04190 { 04191 struct aji_client *client; 04192 struct aji_resource *resource; 04193 const char *name; 04194 struct aji_message *tmp; 04195 04196 switch (cmd) { 04197 case CLI_INIT: 04198 e->command = "jabber test"; 04199 e->usage = 04200 "Usage: jabber test <connection>\n" 04201 " Sends test message for debugging purposes. A specific client\n" 04202 " as configured in jabber.conf must be specified.\n"; 04203 return NULL; 04204 case CLI_GENERATE: 04205 return NULL; 04206 } 04207 04208 if (a->argc != 3) { 04209 return CLI_SHOWUSAGE; 04210 } 04211 name = a->argv[2]; 04212 04213 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 04214 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 04215 return CLI_FAILURE; 04216 } 04217 04218 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 04219 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 04220 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04221 ASTOBJ_RDLOCK(iterator); 04222 ast_verbose("User: %s\n", iterator->name); 04223 for (resource = iterator->resources; resource; resource = resource->next) { 04224 ast_verbose("Resource: %s\n", resource->resource); 04225 if (resource->cap) { 04226 ast_verbose(" client: %s\n", resource->cap->parent->node); 04227 ast_verbose(" version: %s\n", resource->cap->version); 04228 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 04229 } 04230 ast_verbose(" Priority: %d\n", resource->priority); 04231 ast_verbose(" Status: %d\n", resource->status); 04232 ast_verbose(" Message: %s\n", S_OR(resource->description, "")); 04233 } 04234 ASTOBJ_UNLOCK(iterator); 04235 }); 04236 ast_verbose("\nOooh a working message stack!\n"); 04237 AST_LIST_LOCK(&client->messages); 04238 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 04239 //ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 04240 } 04241 AST_LIST_UNLOCK(&client->messages); 04242 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04243 04244 return CLI_SUCCESS; 04245 }
static int aji_tls_handshake | ( | struct aji_client * | client | ) | [static] |
Definition at line 1242 of file res_jabber.c.
References aji_send_header(), ast_debug, aji_client::jid, aji_client::p, aji_client::ssl_context, aji_client::ssl_method, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by aji_act_hook().
01243 { 01244 int ret; 01245 int sock; 01246 01247 ast_debug(1, "Starting TLS handshake\n"); 01248 01249 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 01250 client->ssl_method = SSLv3_method(); 01251 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) { 01252 return IKS_NET_TLSFAIL; 01253 } 01254 01255 /* Create new SSL session */ 01256 if (!(client->ssl_session = SSL_new(client->ssl_context))) { 01257 return IKS_NET_TLSFAIL; 01258 } 01259 01260 /* Enforce TLS on our XMPP connection */ 01261 sock = iks_fd(client->p); 01262 if (!(ret = SSL_set_fd(client->ssl_session, sock))) { 01263 return IKS_NET_TLSFAIL; 01264 } 01265 01266 /* Perform SSL handshake */ 01267 if (!(ret = SSL_connect(client->ssl_session))) { 01268 return IKS_NET_TLSFAIL; 01269 } 01270 01271 client->stream_flags &= (~TRY_SECURE); 01272 client->stream_flags |= SECURE; 01273 01274 /* Sent over the established TLS connection */ 01275 if ((ret = aji_send_header(client, client->jid->server)) != IKS_OK) { 01276 return IKS_NET_TLSFAIL; 01277 } 01278 01279 ast_debug(1, "TLS started with server\n"); 01280 01281 return IKS_OK; 01282 }
void ast_aji_buddy_destroy | ( | struct aji_buddy * | obj | ) |
Destructor function for buddies to be used with ASTOBJ_UNREF
Definition at line 434 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().
00435 { 00436 struct aji_resource *tmp; 00437 00438 while ((tmp = obj->resources)) { 00439 obj->resources = obj->resources->next; 00440 ast_free(tmp->description); 00441 ast_free(tmp); 00442 } 00443 00444 ast_free(obj); 00445 }
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 412 of file res_jabber.c.
References aji_message_destroy(), ast_aji_buddy_destroy(), ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, aji_client::buddies, aji_client::f, aji_message::list, aji_client::messages, aji_client::p, and aji_client::stack.
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_act_hook(), aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_client_connect(), aji_client_info_handler(), aji_create_client(), aji_devstate_cb(), aji_dinfo_handler(), aji_ditems_handler(), aji_handle_pubsub_error(), aji_join_exec(), aji_leave_exec(), aji_log_hook(), aji_mwi_cb(), aji_receive_node_list(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), ast_aji_disconnect(), gtalk_newcall(), gtalk_request(), jingle_newcall(), jingle_request(), manager_jabber_send(), and unload_module().
00413 { 00414 struct aji_message *tmp; 00415 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, ast_aji_buddy_destroy); 00416 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00417 iks_filter_delete(obj->f); 00418 iks_parser_delete(obj->p); 00419 iks_stack_delete(obj->stack); 00420 AST_LIST_LOCK(&obj->messages); 00421 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00422 aji_message_destroy(tmp); 00423 } 00424 AST_LIST_HEAD_DESTROY(&obj->messages); 00425 ast_free(obj); 00426 }
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 2635 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02636 { 02637 int res = 0; 02638 iks *iq = NULL; 02639 iq = iks_new("iq"); 02640 02641 if (iq && client) { 02642 iks_insert_attrib(iq, "type", "get"); 02643 iks_insert_attrib(iq, "to", server); 02644 iks_insert_attrib(iq, "id", client->mid); 02645 ast_aji_increment_mid(client->mid); 02646 ast_aji_send(client, iq); 02647 } else { 02648 ast_log(LOG_ERROR, "Out of memory.\n"); 02649 } 02650 02651 iks_delete(iq); 02652 02653 return res; 02654 }
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 3142 of file res_jabber.c.
References ast_aji_client_destroy(), ast_verb, ASTOBJ_UNREF, aji_client::p, aji_client::ssl_context, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by unload_module().
03143 { 03144 if (client) { 03145 ast_verb(4, "JABBER: Disconnecting\n"); 03146 #ifdef HAVE_OPENSSL 03147 if (client->stream_flags & SECURE) { 03148 SSL_shutdown(client->ssl_session); 03149 SSL_CTX_free(client->ssl_context); 03150 SSL_free(client->ssl_session); 03151 } 03152 #endif 03153 iks_disconnect(client->p); 03154 iks_parser_delete(client->p); 03155 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03156 } 03157 03158 return 1; 03159 }
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)
name | label or JID |
Definition at line 4595 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, clients, and strsep().
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_join_exec(), aji_leave_exec(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), gtalk_create_member(), gtalk_newcall(), gtalk_request(), jingle_create_member(), jingle_newcall(), jingle_request(), and manager_jabber_send().
04596 { 04597 struct aji_client *client = NULL; 04598 char *aux = NULL; 04599 04600 client = ASTOBJ_CONTAINER_FIND(&clients, name); 04601 if (!client && strchr(name, '@')) { 04602 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04603 aux = ast_strdupa(iterator->user); 04604 if (strchr(aux, '/')) { 04605 /* strip resource for comparison */ 04606 aux = strsep(&aux, "/"); 04607 } 04608 if (!strncasecmp(aux, name, strlen(aux))) { 04609 client = ASTOBJ_REF(iterator); 04610 } 04611 }); 04612 } 04613 04614 return client; 04615 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) |
Definition at line 4617 of file res_jabber.c.
References clients.
04618 { 04619 return &clients; 04620 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 2779 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().
02780 { 02781 int i = 0; 02782 02783 for (i = strlen(mid) - 1; i >= 0; i--) { 02784 if (mid[i] != 'z') { 02785 mid[i] = mid[i] + 1; 02786 i = 0; 02787 } else 02788 mid[i] = 'a'; 02789 } 02790 }
int ast_aji_invite_chat | ( | struct aji_client * | client, | |
char * | user, | |||
char * | room, | |||
char * | message | |||
) |
invite to a chatroom.
client | the configured XMPP client we use to connect to a XMPP server | |
user | ||
room | ||
message |
Definition at line 2687 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02688 { 02689 int res = 0; 02690 iks *invite, *body, *namespace; 02691 02692 invite = iks_new("message"); 02693 body = iks_new("body"); 02694 namespace = iks_new("x"); 02695 if (client && invite && body && namespace) { 02696 iks_insert_attrib(invite, "to", user); 02697 iks_insert_attrib(invite, "id", client->mid); 02698 ast_aji_increment_mid(client->mid); 02699 iks_insert_cdata(body, message, 0); 02700 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02701 iks_insert_attrib(namespace, "jid", room); 02702 iks_insert_node(invite, body); 02703 iks_insert_node(invite, namespace); 02704 res = ast_aji_send(client, invite); 02705 } else { 02706 ast_log(LOG_ERROR, "Out of memory.\n"); 02707 } 02708 02709 iks_delete(body); 02710 iks_delete(namespace); 02711 iks_delete(invite); 02712 02713 return res; 02714 }
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 2663 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_join_exec().
02664 { 02665 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL); 02666 }
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 2675 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_leave_exec().
02676 { 02677 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL); 02678 }
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 1439 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().
01440 { 01441 return aji_send_raw(client, iks_string(iks_stack(x), x)); 01442 }
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 2571 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_send_exec(), aji_test(), gtalk_sendtext(), jingle_sendtext(), and manager_jabber_send().
02572 { 02573 return aji_send_raw_chat(client, 0, NULL, address, message); 02574 }
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 2585 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_sendgroup_exec().
02585 { 02586 return aji_send_raw_chat(client, 1, nick, address, message); 02587 }
static int delete_old_messages | ( | struct aji_client * | client, | |
char * | from | |||
) | [static] |
Definition at line 932 of file res_jabber.c.
References aji_message_destroy(), aji_message::arrived, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_tvdiff_sec(), ast_tvnow(), aji_message::from, aji_message::list, LOG_ERROR, aji_client::message_timeout, and aji_client::messages.
Referenced by aji_handle_message(), and delete_old_messages_all().
00933 { 00934 int deleted = 0; 00935 int isold = 0; 00936 struct aji_message *tmp = NULL; 00937 if (!client) { 00938 ast_log(LOG_ERROR, "Cannot find our XMPP client\n"); 00939 return -1; 00940 } 00941 00942 /* remove old messages */ 00943 AST_LIST_LOCK(&client->messages); 00944 if (AST_LIST_EMPTY(&client->messages)) { 00945 AST_LIST_UNLOCK(&client->messages); 00946 return 0; 00947 } 00948 00949 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00950 if (isold) { 00951 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00952 AST_LIST_REMOVE_CURRENT(list); 00953 aji_message_destroy(tmp); 00954 deleted ++; 00955 } 00956 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00957 isold = 1; 00958 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00959 AST_LIST_REMOVE_CURRENT(list); 00960 aji_message_destroy(tmp); 00961 deleted ++; 00962 } 00963 } 00964 } 00965 AST_LIST_TRAVERSE_SAFE_END; 00966 AST_LIST_UNLOCK(&client->messages); 00967 00968 return deleted; 00969 }
static int delete_old_messages_all | ( | struct aji_client * | client | ) | [static] |
Definition at line 979 of file res_jabber.c.
References delete_old_messages().
Referenced by aji_recv_loop().
00980 { 00981 return delete_old_messages(client, NULL); 00982 }
static int gtalk_yuck | ( | iks * | node | ) | [static] |
Definition at line 568 of file res_jabber.c.
References ast_debug.
Referenced by aji_handle_presence().
00569 { 00570 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) { 00571 ast_debug(1, "Found resource with Googletalk voice capabilities\n"); 00572 return 1; 00573 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) { 00574 ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n"); 00575 return 1; 00576 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) { 00577 ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n"); 00578 return 1; 00579 } 00580 00581 return 0; 00582 }
static iks * jabber_make_auth | ( | iksid * | id, | |
const char * | pass, | |||
const char * | sid | |||
) | [static] |
Definition at line 592 of file res_jabber.c.
References ast_sha1_hash().
Referenced by aji_act_hook().
00593 { 00594 iks *x, *y; 00595 x = iks_new("iq"); 00596 iks_insert_attrib(x, "type", "set"); 00597 y = iks_insert(x, "query"); 00598 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00599 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00600 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00601 if (sid) { 00602 char buf[41]; 00603 char sidpass[100]; 00604 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00605 ast_sha1_hash(buf, sidpass); 00606 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00607 } else { 00608 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00609 } 00610 return x; 00611 }
static int load_module | ( | void | ) | [static] |
Definition at line 4749 of file res_jabber.c.
References aji_cli, 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, jabberreceive_function, jabberstatus_function, manager_jabber_send(), and messagelock.
04750 { 04751 ASTOBJ_CONTAINER_INIT(&clients); 04752 if (!aji_reload(0)) 04753 return AST_MODULE_LOAD_DECLINE; 04754 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 04755 ast_register_application_xml(app_ajisend, aji_send_exec); 04756 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec); 04757 ast_register_application_xml(app_ajistatus, aji_status_exec); 04758 ast_register_application_xml(app_ajijoin, aji_join_exec); 04759 ast_register_application_xml(app_ajileave, aji_leave_exec); 04760 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04761 ast_custom_function_register(&jabberstatus_function); 04762 ast_custom_function_register(&jabberreceive_function); 04763 04764 ast_mutex_init(&messagelock); 04765 ast_cond_init(&message_received_condition, NULL); 04766 return 0; 04767 }
static int manager_jabber_send | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4629 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().
04630 { 04631 struct aji_client *client = NULL; 04632 const char *id = astman_get_header(m, "ActionID"); 04633 const char *jabber = astman_get_header(m, "Jabber"); 04634 const char *screenname = astman_get_header(m, "ScreenName"); 04635 const char *message = astman_get_header(m, "Message"); 04636 04637 if (ast_strlen_zero(jabber)) { 04638 astman_send_error(s, m, "No transport specified"); 04639 return 0; 04640 } 04641 if (ast_strlen_zero(screenname)) { 04642 astman_send_error(s, m, "No ScreenName specified"); 04643 return 0; 04644 } 04645 if (ast_strlen_zero(message)) { 04646 astman_send_error(s, m, "No Message specified"); 04647 return 0; 04648 } 04649 04650 astman_send_ack(s, m, "Attempting to send Jabber Message"); 04651 client = ast_aji_get_client(jabber); 04652 if (!client) { 04653 astman_send_error(s, m, "Could not find Sender"); 04654 return 0; 04655 } 04656 if (strchr(screenname, '@') && message) { 04657 ast_aji_send_chat(client, screenname, message); 04658 astman_append(s, "Response: Success\r\n"); 04659 } else { 04660 astman_append(s, "Response: Error\r\n"); 04661 } 04662 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04663 if (!ast_strlen_zero(id)) { 04664 astman_append(s, "ActionID: %s\r\n", id); 04665 } 04666 astman_append(s, "\r\n"); 04667 return 0; 04668 }
static int reload | ( | void | ) | [static] |
Definition at line 4773 of file res_jabber.c.
References aji_reload().
04774 { 04775 aji_reload(1); 04776 return 0; 04777 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4708 of file res_jabber.c.
References aji_cli, 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, clients, device_state_sub, jabberreceive_function, jabberstatus_function, messagelock, and mwi_sub.
04709 { 04710 04711 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04712 ast_unregister_application(app_ajisend); 04713 ast_unregister_application(app_ajisendgroup); 04714 ast_unregister_application(app_ajistatus); 04715 ast_unregister_application(app_ajijoin); 04716 ast_unregister_application(app_ajileave); 04717 ast_manager_unregister("JabberSend"); 04718 ast_custom_function_unregister(&jabberstatus_function); 04719 if (mwi_sub) { 04720 ast_event_unsubscribe(mwi_sub); 04721 } 04722 if (device_state_sub) { 04723 ast_event_unsubscribe(device_state_sub); 04724 } 04725 ast_custom_function_unregister(&jabberreceive_function); 04726 04727 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04728 ASTOBJ_WRLOCK(iterator); 04729 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 04730 iterator->state = AJI_DISCONNECTING; 04731 ASTOBJ_UNLOCK(iterator); 04732 pthread_join(iterator->thread, NULL); 04733 ast_aji_disconnect(iterator); 04734 }); 04735 04736 ASTOBJ_CONTAINER_DESTROYALL(&clients, ast_aji_client_destroy); 04737 ASTOBJ_CONTAINER_DESTROY(&clients); 04738 04739 ast_cond_destroy(&message_received_condition); 04740 ast_mutex_destroy(&messagelock); 04741 04742 return 0; 04743 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 4784 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
char* app_ajijoin = "JabberJoin" [static] |
Definition at line 391 of file res_jabber.c.
char* app_ajileave = "JabberLeave" [static] |
Definition at line 392 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 388 of file res_jabber.c.
char* app_ajisendgroup = "JabberSendGroup" [static] |
Definition at line 389 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 390 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4784 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL [static] |
struct aji_client_container clients [static] |
Definition at line 394 of file res_jabber.c.
Referenced by aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_create_client(), aji_do_set_debug(), aji_reload(), aji_show_buddies(), aji_show_clients(), aji_test(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), jingle_load_config(), load_module(), and unload_module().
struct ast_event_sub* device_state_sub = NULL [static] |
Definition at line 397 of file res_jabber.c.
struct ast_flags globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } [static] |
struct ast_custom_function jabberreceive_function [static] |
Initial value:
{ .name = "JABBER_RECEIVE", .read = acf_jabberreceive_read, }
Definition at line 918 of file res_jabber.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function jabberstatus_function [static] |
Initial value:
{ .name = "JABBER_STATUS", .read = acf_jabberstatus_read, }
Definition at line 755 of file res_jabber.c.
Referenced by load_module(), and unload_module().
ast_cond_t message_received_condition [static] |
Definition at line 398 of file res_jabber.c.
ast_mutex_t messagelock [static] |
Definition at line 399 of file res_jabber.c.
Referenced by acf_jabberreceive_read(), aji_handle_message(), load_module(), and unload_module().
struct ast_event_sub* mwi_sub = NULL [static] |
Definition at line 396 of file res_jabber.c.
Referenced by aji_init_event_distribution(), handle_subscribe(), handle_unsubscribe(), mwi_sub_destroy(), poll_subscribed_mailbox(), poll_subscribed_mailboxes(), and unload_module().
struct ast_flags pubsubflags = { 0 } [static] |
PubSub flags, initialized to default values.
Definition at line 405 of file res_jabber.c.
Referenced by aji_cli_purge_pubsub_nodes(), aji_create_client(), aji_handle_pubsub_error(), and aji_publish_device_state().