#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 = "ac1f6a56484a8820659555499174e588" , .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 4785 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4785 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 3813 of file res_jabber.c.
Referenced by aji_create_pubsub_node().
03814 { 03815 iks *configure, *x, *field_owner, *field_node_type, *field_node_config, 03816 *field_deliver_payload, *field_persist_items, *field_access_model, 03817 *field_pubsub_collection; 03818 configure = iks_insert(pubsub, "configure"); 03819 x = iks_insert(configure, "x"); 03820 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03821 iks_insert_attrib(x, "type", "submit"); 03822 field_owner = iks_insert(x, "field"); 03823 iks_insert_attrib(field_owner, "var", "FORM_TYPE"); 03824 iks_insert_attrib(field_owner, "type", "hidden"); 03825 iks_insert_cdata(iks_insert(field_owner, "value"), 03826 "http://jabber.org/protocol/pubsub#owner", 39); 03827 if (node_type) { 03828 field_node_type = iks_insert(x, "field"); 03829 iks_insert_attrib(field_node_type, "var", "pubsub#node_type"); 03830 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type)); 03831 } 03832 field_node_config = iks_insert(x, "field"); 03833 iks_insert_attrib(field_node_config, "var", "FORM_TYPE"); 03834 iks_insert_attrib(field_node_config, "type", "hidden"); 03835 iks_insert_cdata(iks_insert(field_node_config, "value"), 03836 "http://jabber.org/protocol/pubsub#node_config", 45); 03837 field_deliver_payload = iks_insert(x, "field"); 03838 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads"); 03839 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1); 03840 field_persist_items = iks_insert(x, "field"); 03841 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items"); 03842 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1); 03843 field_access_model = iks_insert(x, "field"); 03844 iks_insert_attrib(field_access_model, "var", "pubsub#access_model"); 03845 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9); 03846 if (node_type && !strcasecmp(node_type, "leaf")) { 03847 field_pubsub_collection = iks_insert(x, "field"); 03848 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection"); 03849 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name, 03850 strlen(collection_name)); 03851 } 03852 return configure; 03853 }
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 3543 of file res_jabber.c.
References aji_pubsub_iq_create().
Referenced by aji_pubsub_purge_nodes(), and aji_request_pubsub_nodes().
03544 { 03545 iks *request = aji_pubsub_iq_create(client, "get"); 03546 iks *query; 03547 query = iks_insert(request, "query"); 03548 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 03549 if (collection) { 03550 iks_insert_attrib(query, "node", collection); 03551 } 03552 return request; 03553 }
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 3371 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().
03373 { 03374 iks *request = aji_pubsub_iq_create(client, "set"); 03375 iks *pubsub, *publish, *item; 03376 pubsub = iks_insert(request, "pubsub"); 03377 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03378 publish = iks_insert(pubsub, "publish"); 03379 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03380 iks_insert_attrib(publish, "node", node); 03381 } else { 03382 iks_insert_attrib(publish, "node", event_type); 03383 } 03384 item = iks_insert(publish, "item"); 03385 iks_insert_attrib(item, "id", node); 03386 return item; 03387 03388 }
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 3861 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.
03862 { 03863 struct aji_client *client; 03864 const char *name; 03865 const char *collection_name; 03866 03867 switch (cmd) { 03868 case CLI_INIT: 03869 e->command = "jabber create collection"; 03870 e->usage = 03871 "Usage: jabber create collection <connection> <collection>\n" 03872 " Creates a PubSub collection node using the account\n" 03873 " as configured in jabber.conf.\n"; 03874 return NULL; 03875 case CLI_GENERATE: 03876 return NULL; 03877 } 03878 03879 if (a->argc != 5) { 03880 return CLI_SHOWUSAGE; 03881 } 03882 name = a->argv[3]; 03883 collection_name = a->argv[4]; 03884 03885 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03886 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03887 return CLI_FAILURE; 03888 } 03889 03890 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03891 aji_create_pubsub_collection(client, collection_name); 03892 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03893 return CLI_SUCCESS; 03894 }
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 3900 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.
03901 { 03902 struct aji_client *client; 03903 const char *name; 03904 const char *collection_name; 03905 const char *leaf_name; 03906 03907 switch (cmd) { 03908 case CLI_INIT: 03909 e->command = "jabber create leaf"; 03910 e->usage = 03911 "Usage: jabber create leaf <connection> <collection> <leaf>\n" 03912 " Creates a PubSub leaf node using the account\n" 03913 " as configured in jabber.conf.\n"; 03914 return NULL; 03915 case CLI_GENERATE: 03916 return NULL; 03917 } 03918 03919 if (a->argc != 6) { 03920 return CLI_SHOWUSAGE; 03921 } 03922 name = a->argv[3]; 03923 collection_name = a->argv[4]; 03924 leaf_name = a->argv[5]; 03925 03926 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03927 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03928 return CLI_FAILURE; 03929 } 03930 03931 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03932 aji_create_pubsub_leaf(client, collection_name, leaf_name); 03933 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03934 return CLI_SUCCESS; 03935 }
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 3714 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.
03716 { 03717 struct aji_client *client; 03718 const char *name; 03719 03720 switch (cmd) { 03721 case CLI_INIT: 03722 e->command = "jabber delete node"; 03723 e->usage = 03724 "Usage: jabber delete node <connection> <node>\n" 03725 " Deletes a node on PubSub server\n" 03726 " as configured in jabber.conf.\n"; 03727 return NULL; 03728 case CLI_GENERATE: 03729 return NULL; 03730 } 03731 03732 if (a->argc != 5) { 03733 return CLI_SHOWUSAGE; 03734 } 03735 name = a->argv[3]; 03736 03737 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03738 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03739 return CLI_FAILURE; 03740 } 03741 aji_delete_pubsub_node(client, a->argv[4]); 03742 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03743 return CLI_SUCCESS; 03744 }
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 3589 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.
03591 { 03592 struct aji_client *client; 03593 const char *name = NULL; 03594 const char *collection = NULL; 03595 03596 switch (cmd) { 03597 case CLI_INIT: 03598 e->command = "jabber list nodes"; 03599 e->usage = 03600 "Usage: jabber list nodes <connection> [collection]\n" 03601 " Lists the user's nodes on the respective connection\n" 03602 " ([connection] as configured in jabber.conf.)\n"; 03603 return NULL; 03604 case CLI_GENERATE: 03605 return NULL; 03606 } 03607 03608 if (a->argc > 5 || a->argc < 4) { 03609 return CLI_SHOWUSAGE; 03610 } else if (a->argc == 4 || a->argc == 5) { 03611 name = a->argv[3]; 03612 } 03613 if (a->argc == 5) { 03614 collection = a->argv[4]; 03615 } 03616 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03617 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03618 return CLI_FAILURE; 03619 } 03620 03621 ast_cli(a->fd, "Listing pubsub nodes.\n"); 03622 aji_request_pubsub_nodes(client, collection); 03623 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03624 return CLI_SUCCESS; 03625 }
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 3634 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.
03636 { 03637 struct aji_client *client; 03638 const char *name; 03639 03640 switch (cmd) { 03641 case CLI_INIT: 03642 e->command = "jabber purge nodes"; 03643 e->usage = 03644 "Usage: jabber purge nodes <connection> <node>\n" 03645 " Purges nodes on PubSub server\n" 03646 " as configured in jabber.conf.\n"; 03647 return NULL; 03648 case CLI_GENERATE: 03649 return NULL; 03650 } 03651 03652 if (a->argc != 5) { 03653 return CLI_SHOWUSAGE; 03654 } 03655 name = a->argv[3]; 03656 03657 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03658 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03659 return CLI_FAILURE; 03660 } 03661 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03662 aji_pubsub_purge_nodes(client, a->argv[4]); 03663 } else { 03664 aji_delete_pubsub_node(client, a->argv[4]); 03665 } 03666 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03667 return CLI_SUCCESS; 03668 }
static int aji_client_connect | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3080 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().
03081 { 03082 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03083 int res = IKS_FILTER_PASS; 03084 03085 if (client) { 03086 if (client->state == AJI_DISCONNECTED) { 03087 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); 03088 client->state = AJI_CONNECTING; 03089 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 03090 if (!client->component) { /*client*/ 03091 aji_get_roster(client); 03092 } 03093 if (client->distribute_events) { 03094 aji_init_event_distribution(client); 03095 } 03096 03097 iks_filter_remove_hook(client->f, aji_client_connect); 03098 /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ 03099 res = IKS_FILTER_EAT; 03100 } 03101 } else { 03102 ast_log(LOG_ERROR, "Out of memory.\n"); 03103 } 03104 03105 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03106 return res; 03107 }
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 3307 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().
03308 { 03309 iks *modify_affiliates = aji_pubsub_iq_create(client, "set"); 03310 iks *pubsub, *affiliations, *affiliate; 03311 pubsub = iks_insert(modify_affiliates, "pubsub"); 03312 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03313 affiliations = iks_insert(pubsub, "affiliations"); 03314 iks_insert_attrib(affiliations, "node", node); 03315 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03316 ASTOBJ_RDLOCK(iterator); 03317 affiliate = iks_insert(affiliations, "affiliation"); 03318 iks_insert_attrib(affiliate, "jid", iterator->name); 03319 iks_insert_attrib(affiliate, "affiliation", "owner"); 03320 ASTOBJ_UNLOCK(iterator); 03321 }); 03322 ast_aji_send(client, modify_affiliates); 03323 iks_delete(modify_affiliates); 03324 }
static int aji_create_buddy | ( | char * | label, | |
struct aji_client * | client | |||
) | [static] |
load config file.
Definition at line 4511 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 4256 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.
04257 { 04258 char *resource; 04259 struct aji_client *client = NULL; 04260 int flag = 0; 04261 04262 client = ASTOBJ_CONTAINER_FIND(&clients, label); 04263 if (!client) { 04264 flag = 1; 04265 client = ast_calloc(1, sizeof(*client)); 04266 if (!client) { 04267 ast_log(LOG_ERROR, "Out of memory!\n"); 04268 return 0; 04269 } 04270 ASTOBJ_INIT(client); 04271 ASTOBJ_WRLOCK(client); 04272 ASTOBJ_CONTAINER_INIT(&client->buddies); 04273 } else { 04274 ASTOBJ_WRLOCK(client); 04275 ASTOBJ_UNMARK(client); 04276 } 04277 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 04278 ast_copy_string(client->name, label, sizeof(client->name)); 04279 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 04280 04281 /* Set default values for the client object */ 04282 client->debug = debug; 04283 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 04284 client->port = 5222; 04285 client->usetls = 1; 04286 client->usesasl = 1; 04287 client->forcessl = 0; 04288 client->keepalive = 1; 04289 client->timeout = 50; 04290 client->message_timeout = 5; 04291 client->distribute_events = 0; 04292 AST_LIST_HEAD_INIT(&client->messages); 04293 client->component = 0; 04294 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 04295 client->priority = 0; 04296 client->status = IKS_SHOW_AVAILABLE; 04297 04298 if (flag) { 04299 client->authorized = 0; 04300 client->state = AJI_DISCONNECTED; 04301 } 04302 while (var) { 04303 if (!strcasecmp(var->name, "username")) { 04304 ast_copy_string(client->user, var->value, sizeof(client->user)); 04305 } else if (!strcasecmp(var->name, "serverhost")) { 04306 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 04307 } else if (!strcasecmp(var->name, "secret")) { 04308 ast_copy_string(client->password, var->value, sizeof(client->password)); 04309 } else if (!strcasecmp(var->name, "statusmessage")) { 04310 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 04311 } else if (!strcasecmp(var->name, "port")) { 04312 client->port = atoi(var->value); 04313 } else if (!strcasecmp(var->name, "timeout")) { 04314 client->message_timeout = atoi(var->value); 04315 } else if (!strcasecmp(var->name, "debug")) { 04316 client->debug = (ast_false(var->value)) ? 0 : 1; 04317 } else if (!strcasecmp(var->name, "type")) { 04318 if (!strcasecmp(var->value, "component")) { 04319 client->component = 1; 04320 if (client->distribute_events) { 04321 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04322 client->distribute_events = 0; 04323 } 04324 } 04325 } else if (!strcasecmp(var->name, "distribute_events")) { 04326 if (ast_true(var->value)) { 04327 if (client->component) { 04328 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04329 } else { 04330 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) { 04331 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n"); 04332 } else { 04333 ast_set_flag(&pubsubflags, AJI_PUBSUB); 04334 client->distribute_events = 1; 04335 } 04336 } 04337 } 04338 } else if (!strcasecmp(var->name, "pubsub_node")) { 04339 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node)); 04340 } else if (!strcasecmp(var->name, "usetls")) { 04341 client->usetls = (ast_false(var->value)) ? 0 : 1; 04342 } else if (!strcasecmp(var->name, "usesasl")) { 04343 client->usesasl = (ast_false(var->value)) ? 0 : 1; 04344 } else if (!strcasecmp(var->name, "forceoldssl")) { 04345 client->forcessl = (ast_false(var->value)) ? 0 : 1; 04346 } else if (!strcasecmp(var->name, "keepalive")) { 04347 client->keepalive = (ast_false(var->value)) ? 0 : 1; 04348 } else if (!strcasecmp(var->name, "autoprune")) { 04349 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 04350 } else if (!strcasecmp(var->name, "autoregister")) { 04351 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 04352 } else if (!strcasecmp(var->name, "auth_policy")) { 04353 if (!strcasecmp(var->value, "accept")) { 04354 ast_set_flag(&client->flags, AJI_AUTOACCEPT); 04355 } else { 04356 ast_clear_flag(&client->flags, AJI_AUTOACCEPT); 04357 } 04358 } else if (!strcasecmp(var->name, "buddy")) { 04359 aji_create_buddy((char *)var->value, client); 04360 } else if (!strcasecmp(var->name, "priority")) { 04361 client->priority = atoi(var->value); 04362 } else if (!strcasecmp(var->name, "status")) { 04363 if (!strcasecmp(var->value, "unavailable")) { 04364 client->status = IKS_SHOW_UNAVAILABLE; 04365 } else if (!strcasecmp(var->value, "available") 04366 || !strcasecmp(var->value, "online")) { 04367 client->status = IKS_SHOW_AVAILABLE; 04368 } else if (!strcasecmp(var->value, "chat") 04369 || !strcasecmp(var->value, "chatty")) { 04370 client->status = IKS_SHOW_CHAT; 04371 } else if (!strcasecmp(var->value, "away")) { 04372 client->status = IKS_SHOW_AWAY; 04373 } else if (!strcasecmp(var->value, "xa") 04374 || !strcasecmp(var->value, "xaway")) { 04375 client->status = IKS_SHOW_XA; 04376 } else if (!strcasecmp(var->value, "dnd")) { 04377 client->status = IKS_SHOW_DND; 04378 } else if (!strcasecmp(var->value, "invisible")) { 04379 #ifdef IKS_SHOW_INVISIBLE 04380 client->status = IKS_SHOW_INVISIBLE; 04381 #else 04382 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 04383 client->status = IKS_SHOW_DND; 04384 #endif 04385 } else { 04386 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 04387 } 04388 } 04389 /* no transport support in this version */ 04390 /* else if (!strcasecmp(var->name, "transport")) 04391 aji_create_transport(var->value, client); 04392 */ 04393 var = var->next; 04394 } 04395 if (!flag) { 04396 ASTOBJ_UNLOCK(client); 04397 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04398 return 1; 04399 } 04400 04401 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 04402 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 04403 if (!client->p) { 04404 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 04405 return 0; 04406 } 04407 client->stack = iks_stack_new(8192, 8192); 04408 if (!client->stack) { 04409 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 04410 return 0; 04411 } 04412 client->f = iks_filter_new(); 04413 if (!client->f) { 04414 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 04415 return 0; 04416 } 04417 if (!strchr(client->user, '/') && !client->component) { /*client */ 04418 resource = NULL; 04419 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 04420 client->jid = iks_id_new(client->stack, resource); 04421 ast_free(resource); 04422 } 04423 } else { 04424 client->jid = iks_id_new(client->stack, client->user); 04425 } 04426 if (client->component) { 04427 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04428 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 04429 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); 04430 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); 04431 } else { 04432 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04433 } 04434 04435 iks_set_log_hook(client->p, aji_log_hook); 04436 ASTOBJ_UNLOCK(client); 04437 ASTOBJ_CONTAINER_LINK(&clients, client); 04438 return 1; 04439 }
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 3769 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_collection(), and aji_handle_pubsub_error().
03771 { 03772 aji_create_pubsub_node(client, "collection", collection_name, NULL); 03773 }
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 3782 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_leafnode(), and aji_handle_pubsub_error().
03784 { 03785 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name); 03786 }
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 3795 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().
03797 { 03798 iks *node = aji_pubsub_iq_create(client, "set"); 03799 iks *pubsub, *create; 03800 pubsub = iks_insert(node, "pubsub"); 03801 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03802 create = iks_insert(pubsub, "create"); 03803 iks_insert_attrib(create, "node", name); 03804 aji_build_node_config(pubsub, node_type, collection_name); 03805 ast_aji_send(client, node); 03806 aji_create_affiliations(client, name); 03807 iks_delete(node); 03808 return 0; 03809 }
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 3687 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().
03688 { 03689 03690 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03691 iks *item = NULL; 03692 if (iks_has_children(pak->query)) { 03693 item = iks_first_tag(pak->query); 03694 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial, 03695 iks_find_attrib(item, "node")); 03696 while ((item = iks_next_tag(item))) { 03697 aji_delete_pubsub_node(client, iks_find_attrib(item, "node")); 03698 } 03699 } 03700 if (item) { 03701 iks_delete(item); 03702 } 03703 return IKS_FILTER_EAT; 03704 }
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 3752 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().
03753 { 03754 iks *request = aji_pubsub_iq_create(client, "set"); 03755 iks *pubsub, *delete; 03756 pubsub = iks_insert(request, "pubsub"); 03757 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03758 delete = iks_insert(pubsub, "delete"); 03759 iks_insert_attrib(delete, "node", node_name); 03760 ast_aji_send(client, request); 03761 }
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 3199 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().
03200 { 03201 const char *device; 03202 const char *device_state; 03203 struct aji_client *client; 03204 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03205 { 03206 /* If the event didn't originate from this server, don't send it back out. */ 03207 ast_log(LOG_DEBUG, "Returning here\n"); 03208 return; 03209 } 03210 03211 client = ASTOBJ_REF((struct aji_client *) data); 03212 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); 03213 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); 03214 aji_publish_device_state(client, device, device_state); 03215 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03216 }
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 4074 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.
04075 { 04076 switch (cmd) { 04077 case CLI_INIT: 04078 e->command = "jabber reload"; 04079 e->usage = 04080 "Usage: jabber reload\n" 04081 " Reloads the Jabber module.\n"; 04082 return NULL; 04083 case CLI_GENERATE: 04084 return NULL; 04085 } 04086 04087 aji_reload(1); 04088 ast_cli(a->fd, "Jabber Reloaded.\n"); 04089 return CLI_SUCCESS; 04090 }
static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4032 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.
04033 { 04034 switch (cmd) { 04035 case CLI_INIT: 04036 e->command = "jabber set debug {on|off}"; 04037 e->usage = 04038 "Usage: jabber set debug {on|off}\n" 04039 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 04040 return NULL; 04041 case CLI_GENERATE: 04042 return NULL; 04043 } 04044 04045 if (a->argc != e->args) { 04046 return CLI_SHOWUSAGE; 04047 } 04048 04049 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 04050 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04051 ASTOBJ_RDLOCK(iterator); 04052 iterator->debug = 1; 04053 ASTOBJ_UNLOCK(iterator); 04054 }); 04055 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 04056 return CLI_SUCCESS; 04057 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 04058 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04059 ASTOBJ_RDLOCK(iterator); 04060 iterator->debug = 0; 04061 ASTOBJ_UNLOCK(iterator); 04062 }); 04063 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 04064 return CLI_SUCCESS; 04065 } 04066 return CLI_SHOWUSAGE; /* defaults to invalid */ 04067 }
static int aji_filter_roster | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2943 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().
02944 { 02945 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02946 int flag = 0; 02947 iks *x = NULL; 02948 struct aji_buddy *buddy; 02949 02950 client->state = AJI_CONNECTED; 02951 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02952 ASTOBJ_RDLOCK(iterator); 02953 x = iks_child(pak->query); 02954 flag = 0; 02955 while (x) { 02956 if (!iks_strcmp(iks_name(x), "item")) { 02957 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02958 flag = 1; 02959 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02960 } 02961 } 02962 x = iks_next(x); 02963 } 02964 if (!flag) { 02965 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02966 } 02967 iks_delete(x); 02968 02969 ASTOBJ_UNLOCK(iterator); 02970 }); 02971 02972 x = iks_child(pak->query); 02973 while (x) { 02974 flag = 0; 02975 if (iks_strcmp(iks_name(x), "item") == 0) { 02976 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02977 ASTOBJ_RDLOCK(iterator); 02978 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02979 flag = 1; 02980 ASTOBJ_UNLOCK(iterator); 02981 }); 02982 02983 if (flag) { 02984 /* found buddy, don't create a new one */ 02985 x = iks_next(x); 02986 continue; 02987 } 02988 02989 buddy = ast_calloc(1, sizeof(*buddy)); 02990 if (!buddy) { 02991 ast_log(LOG_WARNING, "Out of memory\n"); 02992 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02993 return 0; 02994 } 02995 ASTOBJ_INIT(buddy); 02996 ASTOBJ_WRLOCK(buddy); 02997 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02998 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02999 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 03000 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 03001 ASTOBJ_MARK(buddy); 03002 } else if (ast_test_flag(&client->flags, AJI_AUTOREGISTER)) { 03003 if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 03004 /* subscribe to buddy's presence only 03005 if we really need to */ 03006 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 03007 } 03008 } 03009 ASTOBJ_UNLOCK(buddy); 03010 if (buddy) { 03011 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 03012 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 03013 } 03014 } 03015 x = iks_next(x); 03016 } 03017 03018 iks_delete(x); 03019 aji_pruneregister(client); 03020 03021 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03022 return IKS_FILTER_EAT; 03023 }
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 3057 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().
03058 { 03059 iks *roster = NULL; 03060 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 03061 03062 if (roster) { 03063 iks_insert_attrib(roster, "id", "roster"); 03064 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 03065 ast_aji_send(client, roster); 03066 } 03067 03068 iks_delete(roster); 03069 03070 return 1; 03071 }
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_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvnow(), delete_old_messages(), aji_message::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_free(insert); 02256 ast_log(LOG_ERROR, "Memory allocation failure\n"); 02257 return; 02258 } 02259 ast_debug(3, "message comes from %s\n", insert->from); 02260 } 02261 02262 /* remove old messages received from this JID 02263 * and insert received message */ 02264 deleted = delete_old_messages(client, pak->from->partial); 02265 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 02266 AST_LIST_LOCK(&client->messages); 02267 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 02268 AST_LIST_UNLOCK(&client->messages); 02269 }
static void aji_handle_presence | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2277 of file res_jabber.c.
References AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_buddy_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_strdup, ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, aji_resource::description, EVENT_FLAG_USER, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, manager_event, aji_client::mid, aji_client::name, aji_resource::next, aji_resource::priority, aji_resource::resource, aji_buddy::resources, S_OR, aji_client::state, aji_resource::status, aji_client::status, status, and type.
Referenced by aji_act_hook().
02278 { 02279 int status, priority; 02280 struct aji_buddy *buddy; 02281 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02282 char *ver, *node, *descrip, *type; 02283 02284 if (client->state != AJI_CONNECTED) 02285 aji_create_buddy(pak->from->partial, client); 02286 02287 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02288 if (!buddy && pak->from->partial) { 02289 /* allow our jid to be used to log in with another resource */ 02290 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02291 aji_create_buddy(pak->from->partial, client); 02292 else 02293 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02294 return; 02295 } 02296 type = iks_find_attrib(pak->x, "type"); 02297 if (client->component && type &&!strcasecmp("probe", type)) { 02298 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02299 ast_verbose("what i was looking for \n"); 02300 } 02301 ASTOBJ_WRLOCK(buddy); 02302 status = (pak->show) ? pak->show : 6; 02303 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02304 tmp = buddy->resources; 02305 descrip = ast_strdup(iks_find_cdata(pak->x, "status")); 02306 02307 while (tmp && pak->from->resource) { 02308 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02309 tmp->status = status; 02310 if (tmp->description) { 02311 ast_free(tmp->description); 02312 } 02313 tmp->description = descrip; 02314 found = tmp; 02315 if (status == 6) { /* Sign off Destroy resource */ 02316 if (last && found->next) { 02317 last->next = found->next; 02318 } else if (!last) { 02319 if (found->next) { 02320 buddy->resources = found->next; 02321 } else { 02322 buddy->resources = NULL; 02323 } 02324 } else if (!found->next) { 02325 if (last) { 02326 last->next = NULL; 02327 } else { 02328 buddy->resources = NULL; 02329 } 02330 } 02331 ast_free(found); 02332 found = NULL; 02333 break; 02334 } 02335 /* resource list is sorted by descending priority */ 02336 if (tmp->priority != priority) { 02337 found->priority = priority; 02338 if (!last && !found->next) { 02339 /* resource was found to be unique, 02340 leave loop */ 02341 break; 02342 } 02343 /* search for resource in our list 02344 and take it out for the moment */ 02345 if (last) { 02346 last->next = found->next; 02347 } else { 02348 buddy->resources = found->next; 02349 } 02350 02351 last = NULL; 02352 tmp = buddy->resources; 02353 if (!buddy->resources) { 02354 buddy->resources = found; 02355 } 02356 /* priority processing */ 02357 while (tmp) { 02358 /* insert resource back according to 02359 its priority value */ 02360 if (found->priority > tmp->priority) { 02361 if (last) { 02362 /* insert within list */ 02363 last->next = found; 02364 } 02365 found->next = tmp; 02366 if (!last) { 02367 /* insert on top */ 02368 buddy->resources = found; 02369 } 02370 break; 02371 } 02372 if (!tmp->next) { 02373 /* insert at the end of the list */ 02374 tmp->next = found; 02375 found->next = NULL; 02376 break; 02377 } 02378 last = tmp; 02379 tmp = tmp->next; 02380 } 02381 } 02382 break; 02383 } 02384 last = tmp; 02385 tmp = tmp->next; 02386 } 02387 02388 /* resource not found in our list, create it */ 02389 if (!found && status != 6 && pak->from->resource) { 02390 found = ast_calloc(1, sizeof(*found)); 02391 02392 if (!found) { 02393 ast_log(LOG_ERROR, "Out of memory!\n"); 02394 ASTOBJ_UNLOCK(buddy); 02395 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02396 return; 02397 } 02398 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02399 found->status = status; 02400 found->description = descrip; 02401 found->priority = priority; 02402 found->next = NULL; 02403 last = NULL; 02404 tmp = buddy->resources; 02405 while (tmp) { 02406 if (found->priority > tmp->priority) { 02407 if (last) { 02408 last->next = found; 02409 } 02410 found->next = tmp; 02411 if (!last) { 02412 buddy->resources = found; 02413 } 02414 break; 02415 } 02416 if (!tmp->next) { 02417 tmp->next = found; 02418 break; 02419 } 02420 last = tmp; 02421 tmp = tmp->next; 02422 } 02423 if (!tmp) { 02424 buddy->resources = found; 02425 } 02426 } 02427 02428 ASTOBJ_UNLOCK(buddy); 02429 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02430 02431 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02432 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02433 02434 /* handle gmail client's special caps:c tag */ 02435 if (!node && !ver) { 02436 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02437 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02438 } 02439 02440 /* retrieve capabilites of the new resource */ 02441 if (status != 6 && found && !found->cap) { 02442 found->cap = aji_find_version(node, ver, pak); 02443 if (gtalk_yuck(pak->x)) { /* gtalk should do discover */ 02444 found->cap->jingle = 1; 02445 } 02446 if (found->cap->jingle) { 02447 ast_debug(1, "Special case for google till they support discover.\n"); 02448 } else { 02449 iks *iq, *query; 02450 iq = iks_new("iq"); 02451 query = iks_new("query"); 02452 if (query && iq) { 02453 iks_insert_attrib(iq, "type", "get"); 02454 iks_insert_attrib(iq, "to", pak->from->full); 02455 iks_insert_attrib(iq, "from", client->jid->full); 02456 iks_insert_attrib(iq, "id", client->mid); 02457 ast_aji_increment_mid(client->mid); 02458 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02459 iks_insert_node(iq, query); 02460 ast_aji_send(client, iq); 02461 } else { 02462 ast_log(LOG_ERROR, "Out of memory.\n"); 02463 } 02464 iks_delete(query); 02465 iks_delete(iq); 02466 } 02467 } 02468 switch (pak->subtype) { 02469 case IKS_TYPE_AVAILABLE: 02470 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 02471 break; 02472 case IKS_TYPE_UNAVAILABLE: 02473 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 02474 break; 02475 default: 02476 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 02477 } 02478 switch (pak->show) { 02479 case IKS_SHOW_UNAVAILABLE: 02480 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02481 break; 02482 case IKS_SHOW_AVAILABLE: 02483 ast_debug(3, "JABBER: type is available\n"); 02484 break; 02485 case IKS_SHOW_CHAT: 02486 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02487 break; 02488 case IKS_SHOW_AWAY: 02489 ast_debug(3, "JABBER: type is away\n"); 02490 break; 02491 case IKS_SHOW_XA: 02492 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02493 break; 02494 case IKS_SHOW_DND: 02495 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02496 break; 02497 default: 02498 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 02499 } 02500 02501 if (found) { 02502 manager_event(EVENT_FLAG_USER, "JabberStatus", 02503 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 02504 "\r\nDescription: %s\r\n", 02505 client->name, pak->from->partial, found->resource, found->status, 02506 found->priority, S_OR(found->description, "")); 02507 } else { 02508 manager_event(EVENT_FLAG_USER, "JabberStatus", 02509 "Account: %s\r\nJID: %s\r\nStatus: %d\r\n", 02510 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE); 02511 } 02512 }
static int aji_handle_pubsub_error | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3462 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().
03463 { 03464 char *node_name; 03465 char *error; 03466 int error_num; 03467 iks *orig_request; 03468 iks *orig_pubsub = iks_find(pak->x, "pubsub"); 03469 struct aji_client *client; 03470 if (!orig_pubsub) { 03471 ast_log(LOG_ERROR, "Error isn't a PubSub error, why are we here?\n"); 03472 return IKS_FILTER_EAT; 03473 } 03474 orig_request = iks_child(orig_pubsub); 03475 error = iks_find_attrib(iks_find(pak->x, "error"), "code"); 03476 node_name = iks_find_attrib(orig_request, "node"); 03477 if (!sscanf(error, "%30d", &error_num)) { 03478 return IKS_FILTER_EAT; 03479 } 03480 if (error_num > 399 && error_num < 500 && error_num != 404) { 03481 ast_log(LOG_ERROR, 03482 "Error performing operation on PubSub node %s, %s.\n", node_name, error); 03483 return IKS_FILTER_EAT; 03484 } else if (error_num > 499 && error_num < 600) { 03485 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error); 03486 return IKS_FILTER_EAT; 03487 } 03488 03489 client = ASTOBJ_REF((struct aji_client *) data); 03490 03491 if (!strcasecmp(iks_name(orig_request), "publish")) { 03492 iks *request; 03493 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03494 if (iks_find(iks_find(orig_request, "item"), "state")) { 03495 aji_create_pubsub_leaf(client, "device_state", node_name); 03496 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) { 03497 aji_create_pubsub_leaf(client, "message_waiting", node_name); 03498 } 03499 } else { 03500 aji_create_pubsub_node(client, NULL, node_name, NULL); 03501 } 03502 request = aji_pubsub_iq_create(client, "set"); 03503 iks_insert_node(request, orig_pubsub); 03504 ast_aji_send(client, request); 03505 iks_delete(request); 03506 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03507 return IKS_FILTER_EAT; 03508 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) { 03509 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03510 aji_create_pubsub_collection(client, node_name); 03511 } else { 03512 aji_create_pubsub_node(client, NULL, node_name, NULL); 03513 } 03514 } 03515 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03516 return IKS_FILTER_EAT; 03517 }
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 3252 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().
03253 { 03254 char *item_id, *device_state, *context; 03255 int oldmsgs, newmsgs; 03256 iks *item, *item_content; 03257 struct ast_eid pubsub_eid; 03258 struct ast_event *event; 03259 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); 03260 if (!item) { 03261 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); 03262 return IKS_FILTER_EAT; 03263 } 03264 item_id = iks_find_attrib(item, "id"); 03265 item_content = iks_child(item); 03266 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid")); 03267 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) { 03268 ast_log(LOG_DEBUG, "Returning here, eid of incoming event matches ours!\n"); 03269 return IKS_FILTER_EAT; 03270 } 03271 if (!strcasecmp(iks_name(item_content), "state")) { 03272 device_state = iks_find_cdata(item, "state"); 03273 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, 03274 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, 03275 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, 03276 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03277 AST_EVENT_IE_END))) { 03278 return IKS_FILTER_EAT; 03279 } 03280 } else if (!strcasecmp(iks_name(item_content), "mailbox")) { 03281 context = strsep(&item_id, "@"); 03282 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs); 03283 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs); 03284 if (!(event = ast_event_new(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX, 03285 AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_CONTEXT, 03286 AST_EVENT_IE_PLTYPE_STR, context, AST_EVENT_IE_OLDMSGS, 03287 AST_EVENT_IE_PLTYPE_UINT, oldmsgs, AST_EVENT_IE_NEWMSGS, 03288 AST_EVENT_IE_PLTYPE_UINT, newmsgs, AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, 03289 &pubsub_eid, sizeof(pubsub_eid), AST_EVENT_IE_END))) { 03290 return IKS_FILTER_EAT; 03291 } 03292 } else { 03293 ast_log(LOG_DEBUG, "Don't know how to handle PubSub event of type %s\n", 03294 iks_name(item_content)); 03295 return IKS_FILTER_EAT; 03296 } 03297 ast_event_queue_and_cache(event); 03298 return IKS_FILTER_EAT; 03299 }
static void aji_handle_subscribe | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2521 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().
02522 { 02523 iks *presence = NULL, *status = NULL; 02524 struct aji_buddy* buddy = NULL; 02525 02526 switch (pak->subtype) { 02527 case IKS_TYPE_SUBSCRIBE: 02528 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) { 02529 presence = iks_new("presence"); 02530 status = iks_new("status"); 02531 if (presence && status) { 02532 iks_insert_attrib(presence, "type", "subscribed"); 02533 iks_insert_attrib(presence, "to", pak->from->full); 02534 iks_insert_attrib(presence, "from", client->jid->full); 02535 if (pak->id) 02536 iks_insert_attrib(presence, "id", pak->id); 02537 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02538 iks_insert_node(presence, status); 02539 ast_aji_send(client, presence); 02540 } else { 02541 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02542 } 02543 02544 iks_delete(presence); 02545 iks_delete(status); 02546 } 02547 02548 if (client->component) 02549 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02550 case IKS_TYPE_SUBSCRIBED: 02551 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02552 if (!buddy && pak->from->partial) { 02553 aji_create_buddy(pak->from->partial, client); 02554 } else if (buddy) { 02555 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02556 } 02557 default: 02558 if (option_verbose > 4) { 02559 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 02560 } 02561 } 02562 }
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 3223 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().
03224 { 03225 if (!mwi_sub) { 03226 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription", 03227 client, AST_EVENT_IE_END); 03228 } 03229 if (!device_state_sub) { 03230 if (ast_enable_distributed_devstate()) { 03231 return; 03232 } 03233 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 03234 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END); 03235 ast_event_dump_cache(device_state_sub); 03236 } 03237 03238 aji_pubsub_subscribe(client, "device_state"); 03239 aji_pubsub_subscribe(client, "message_waiting"); 03240 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE, 03241 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE); 03242 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE, 03243 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE); 03244 03245 }
static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 3115 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().
03116 { 03117 int connected = IKS_NET_NOCONN; 03118 03119 #ifdef HAVE_OPENSSL 03120 /* reset stream flags */ 03121 client->stream_flags = 0; 03122 #endif 03123 /* If it's a component, connect to user, otherwise, connect to server */ 03124 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 03125 03126 if (connected == IKS_NET_NOCONN) { 03127 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 03128 return IKS_HOOK; 03129 } else if (connected == IKS_NET_NODNS) { 03130 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, 03131 S_OR(client->serverhost, client->jid->server)); 03132 return IKS_HOOK; 03133 } 03134 03135 return IKS_OK; 03136 }
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 4538 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_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, globalflags, JABBER_CONFIG, LOG_WARNING, and var.
Referenced by aji_reload().
04539 { 04540 char *cat = NULL; 04541 int debug = 0; 04542 struct ast_config *cfg = NULL; 04543 struct ast_variable *var = NULL; 04544 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04545 04546 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 04547 return -1; 04548 } 04549 04550 /* Reset flags to default value */ 04551 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT); 04552 04553 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 04554 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 04555 return 0; 04556 } 04557 04558 cat = ast_category_browse(cfg, NULL); 04559 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 04560 if (!strcasecmp(var->name, "debug")) { 04561 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 04562 } else if (!strcasecmp(var->name, "autoprune")) { 04563 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 04564 } else if (!strcasecmp(var->name, "autoregister")) { 04565 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 04566 } else if (!strcasecmp(var->name, "collection_nodes")) { 04567 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248); 04568 } else if (!strcasecmp(var->name, "pubsub_autocreate")) { 04569 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE); 04570 } else if (!strcasecmp(var->name, "auth_policy")) { 04571 if (!strcasecmp(var->value, "accept")) { 04572 ast_set_flag(&globalflags, AJI_AUTOACCEPT); 04573 } else { 04574 ast_clear_flag(&globalflags, AJI_AUTOACCEPT); 04575 } 04576 } 04577 } 04578 04579 while (cat) { 04580 if (strcasecmp(cat, "general")) { 04581 var = ast_variable_browse(cfg, cat); 04582 aji_create_client(cat, var, debug); 04583 } 04584 cat = ast_category_browse(cfg, cat); 04585 } 04586 ast_config_destroy(cfg); /* or leak memory */ 04587 return 1; 04588 }
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 3168 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().
03169 { 03170 const char *mailbox; 03171 const char *context; 03172 char oldmsgs[10]; 03173 char newmsgs[10]; 03174 struct aji_client *client; 03175 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03176 { 03177 /* If the event didn't originate from this server, don't send it back out. */ 03178 ast_log(LOG_DEBUG, "Returning here\n"); 03179 return; 03180 } 03181 03182 client = ASTOBJ_REF((struct aji_client *) data); 03183 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX); 03184 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT); 03185 snprintf(oldmsgs, sizeof(oldmsgs), "%d", 03186 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS)); 03187 snprintf(newmsgs, sizeof(newmsgs), "%d", 03188 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS)); 03189 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs); 03190 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03191 03192 }
static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2889 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.
02890 { 02891 iks *removeiq = iks_new("iq"); 02892 iks *removequery = iks_new("query"); 02893 iks *removeitem = iks_new("item"); 02894 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02895 if (!client || !removeiq || !removequery || !removeitem || !send) { 02896 ast_log(LOG_ERROR, "Out of memory.\n"); 02897 goto safeout; 02898 } 02899 02900 iks_insert_node(removeiq, removequery); 02901 iks_insert_node(removequery, removeitem); 02902 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02903 ASTOBJ_RDLOCK(iterator); 02904 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02905 * be called at the same time */ 02906 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02907 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02908 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02909 " so I am no longer subscribing to your presence.\n")); 02910 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02911 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02912 " your access to my presence.\n")); 02913 iks_insert_attrib(removeiq, "from", client->jid->full); 02914 iks_insert_attrib(removeiq, "type", "set"); 02915 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02916 iks_insert_attrib(removeitem, "jid", iterator->name); 02917 iks_insert_attrib(removeitem, "subscription", "remove"); 02918 ast_aji_send(client, removeiq); 02919 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02920 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02921 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02922 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02923 } 02924 ASTOBJ_UNLOCK(iterator); 02925 }); 02926 02927 safeout: 02928 iks_delete(removeiq); 02929 iks_delete(removequery); 02930 iks_delete(removeitem); 02931 iks_delete(send); 02932 02933 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, ast_aji_buddy_destroy); 02934 }
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 3397 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().
03399 { 03400 iks *request = aji_build_publish_skeleton(client, device, "device_state"); 03401 iks *state; 03402 char eid_str[20]; 03403 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { 03404 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03405 aji_create_pubsub_node(client, "leaf", device, "device_state"); 03406 } else { 03407 aji_create_pubsub_node(client, NULL, device, NULL); 03408 } 03409 } 03410 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03411 state = iks_insert(request, "state"); 03412 iks_insert_attrib(state, "xmlns", "http://asterisk.org"); 03413 iks_insert_attrib(state, "eid", eid_str); 03414 iks_insert_cdata(state, device_state, strlen(device_state)); 03415 ast_aji_send(client, iks_root(request)); 03416 iks_delete(request); 03417 }
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 3426 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().
03428 { 03429 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT]; 03430 char eid_str[20]; 03431 iks *mailbox_node, *request; 03432 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); 03433 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting"); 03434 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03435 mailbox_node = iks_insert(request, "mailbox"); 03436 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org"); 03437 iks_insert_attrib(mailbox_node, "eid", eid_str); 03438 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs)); 03439 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs)); 03440 ast_aji_send(client, iks_root(request)); 03441 iks_delete(request); 03442 }
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 3450 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().
03451 { 03452 iks *request = iks_new("iq"); 03453 03454 iks_insert_attrib(request, "to", client->pubsub_node); 03455 iks_insert_attrib(request, "from", client->jid->full); 03456 iks_insert_attrib(request, "type", type); 03457 ast_aji_increment_mid(client->mid); 03458 iks_insert_attrib(request, "id", client->mid); 03459 return request; 03460 }
static void aji_pubsub_purge_nodes | ( | struct aji_client * | client, | |
const char * | collection_name | |||
) | [static] |
Definition at line 3670 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().
03671 { 03672 iks *request = aji_build_node_request(client, collection_name); 03673 ast_aji_send(client, request); 03674 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE, 03675 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03676 IKS_RULE_DONE); 03677 ast_aji_send(client, request); 03678 iks_delete(request); 03679 }
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 3332 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().
03333 { 03334 iks *request = aji_pubsub_iq_create(client, "set"); 03335 iks *pubsub, *subscribe; 03336 03337 pubsub = iks_insert(request, "pubsub"); 03338 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03339 subscribe = iks_insert(pubsub, "subscribe"); 03340 iks_insert_attrib(subscribe, "jid", client->jid->partial); 03341 iks_insert_attrib(subscribe, "node", node); 03342 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03343 iks *options, *x, *sub_options, *sub_type, *sub_depth; 03344 options = iks_insert(pubsub, "options"); 03345 x = iks_insert(options, "x"); 03346 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03347 iks_insert_attrib(x, "type", "submit"); 03348 sub_options = iks_insert(x, "field"); 03349 iks_insert_attrib(sub_options, "var", "FORM_TYPE"); 03350 iks_insert_attrib(sub_options, "type", "hidden"); 03351 iks_insert_cdata(iks_insert(sub_options, "value"), 03352 "http://jabber.org/protocol/pubsub#subscribe_options", 51); 03353 sub_type = iks_insert(x, "field"); 03354 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type"); 03355 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5); 03356 sub_depth = iks_insert(x, "field"); 03357 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth"); 03358 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3); 03359 } 03360 ast_aji_send(client, request); 03361 iks_delete(request); 03362 }
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 3561 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().
03562 { 03563 03564 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03565 iks *item = NULL; 03566 if (iks_has_children(pak->query)) { 03567 item = iks_first_tag(pak->query); 03568 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial, 03569 iks_find_attrib(item, "node")); 03570 while ((item = iks_next_tag(item))) { 03571 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node")); 03572 } 03573 } 03574 if (item) { 03575 iks_delete(item); 03576 } 03577 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03578 return IKS_FILTER_EAT; 03579 }
static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 3031 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().
03032 { 03033 int res = 0; 03034 03035 if (client->state) { 03036 client->state = AJI_DISCONNECTED; 03037 } 03038 client->timeout = 50; 03039 if (client->p) { 03040 iks_parser_reset(client->p); 03041 } 03042 if (client->authorized) { 03043 client->authorized = 0; 03044 } 03045 03046 res = aji_initialize(client); 03047 03048 return res; 03049 }
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 2723 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().
02724 { 02725 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02726 int res = IKS_HOOK; 02727 02728 while (res != IKS_OK) { 02729 ast_debug(3, "JABBER: Connecting.\n"); 02730 res = aji_reconnect(client); 02731 sleep(4); 02732 } 02733 02734 do { 02735 if (res == IKS_NET_RWERR || client->timeout == 0) { 02736 while (res != IKS_OK) { 02737 ast_debug(3, "JABBER: reconnecting.\n"); 02738 res = aji_reconnect(client); 02739 sleep(4); 02740 } 02741 } 02742 02743 res = aji_recv(client, 1); 02744 02745 if (client->state == AJI_DISCONNECTING) { 02746 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02747 pthread_exit(NULL); 02748 } 02749 02750 /* Decrease timeout if no data received, and delete 02751 * old messages globally */ 02752 if (res == IKS_NET_EXPIRED) { 02753 client->timeout--; 02754 delete_old_messages_all(client); 02755 } 02756 if (res == IKS_HOOK) { 02757 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02758 } else if (res == IKS_NET_TLSFAIL) { 02759 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02760 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02761 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02762 if (res == IKS_OK) { 02763 client->timeout = 50; 02764 } else { 02765 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02766 } 02767 } else if (res == IKS_NET_RWERR) { 02768 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02769 } 02770 } while (client); 02771 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02772 return 0; 02773 }
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 4675 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().
04676 { 04677 int res; 04678 04679 ASTOBJ_CONTAINER_MARKALL(&clients); 04680 if (!(res = aji_load_config(reload))) { 04681 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 04682 return 0; 04683 } else if (res == -1) 04684 return 1; 04685 04686 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, ast_aji_client_destroy); 04687 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04688 ASTOBJ_RDLOCK(iterator); 04689 if (iterator->state == AJI_DISCONNECTED) { 04690 if (!iterator->thread) 04691 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 04692 } else if (iterator->state == AJI_CONNECTING) { 04693 aji_get_roster(iterator); 04694 if (iterator->distribute_events) { 04695 aji_init_event_distribution(iterator); 04696 } 04697 } 04698 04699 ASTOBJ_UNLOCK(iterator); 04700 }); 04701 04702 return 1; 04703 }
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 3525 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().
03526 { 03527 iks *request = aji_build_node_request(client, collection); 03528 03529 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE, 03530 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03531 IKS_RULE_DONE); 03532 ast_aji_send(client, request); 03533 iks_delete(request); 03534 03535 }
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 2599 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().
02600 { 02601 int res = 0; 02602 iks *message_packet = NULL; 02603 char from[AJI_MAX_JIDLEN]; 02604 /* the nickname is used only in component mode */ 02605 if (nick && client->component) { 02606 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 02607 } else { 02608 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 02609 } 02610 02611 if (client->state != AJI_CONNECTED) { 02612 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02613 return -1; 02614 } 02615 02616 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message); 02617 if (!message_packet) { 02618 ast_log(LOG_ERROR, "Out of memory.\n"); 02619 return -1; 02620 } 02621 iks_insert_attrib(message_packet, "from", from); 02622 res = ast_aji_send(client, message_packet); 02623 iks_delete(message_packet); 02624 02625 return res; 02626 }
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 3991 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().
03992 { 03993 int res = 0; 03994 iks *presence = NULL, *x = NULL; 03995 char from[AJI_MAX_JIDLEN]; 03996 char roomid[AJI_MAX_JIDLEN]; 03997 03998 presence = iks_make_pres(level, NULL); 03999 x = iks_new("x"); 04000 04001 if (client->component) { 04002 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 04003 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick); 04004 } else { 04005 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 04006 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user); 04007 } 04008 04009 if (!presence || !x || !client) { 04010 ast_log(LOG_ERROR, "Out of memory.\n"); 04011 res = -1; 04012 goto safeout; 04013 } else { 04014 iks_insert_attrib(presence, "to", roomid); 04015 iks_insert_attrib(presence, "from", from); 04016 iks_insert_attrib(x, "xmlns", MUC_NS); 04017 iks_insert_node(presence, x); 04018 res = ast_aji_send(client, presence); 04019 } 04020 04021 safeout: 04022 iks_delete(presence); 04023 iks_delete(x); 04024 return res; 04025 }
static void aji_set_presence | ( | struct aji_client * | client, | |
char * | to, | |||
char * | from, | |||
int | level, | |||
char * | desc | |||
) | [static] |
Definition at line 3949 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().
03950 { 03951 iks *presence = iks_make_pres(level, desc); 03952 iks *cnode = iks_new("c"); 03953 iks *priority = iks_new("priority"); 03954 char priorityS[10]; 03955 03956 if (presence && cnode && client && priority) { 03957 if (to) { 03958 iks_insert_attrib(presence, "to", to); 03959 } 03960 if (from) { 03961 iks_insert_attrib(presence, "from", from); 03962 } 03963 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 03964 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 03965 iks_insert_node(presence, priority); 03966 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 03967 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 03968 iks_insert_attrib(cnode, "ext", "voice-v1"); 03969 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 03970 iks_insert_node(presence, cnode); 03971 ast_aji_send(client, presence); 03972 } else { 03973 ast_log(LOG_ERROR, "Out of memory.\n"); 03974 } 03975 03976 iks_delete(cnode); 03977 iks_delete(presence); 03978 iks_delete(priority); 03979 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4143 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.
04144 { 04145 struct aji_resource *resource; 04146 struct aji_client *client; 04147 04148 switch (cmd) { 04149 case CLI_INIT: 04150 e->command = "jabber show buddies"; 04151 e->usage = 04152 "Usage: jabber show buddies\n" 04153 " Shows buddy lists of our clients\n"; 04154 return NULL; 04155 case CLI_GENERATE: 04156 return NULL; 04157 } 04158 04159 ast_cli(a->fd, "Jabber buddy lists\n"); 04160 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04161 ast_cli(a->fd, "Client: %s\n", iterator->user); 04162 client = iterator; 04163 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04164 ASTOBJ_RDLOCK(iterator); 04165 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name); 04166 if (!iterator->resources) 04167 ast_cli(a->fd, "\t\tResource: None\n"); 04168 for (resource = iterator->resources; resource; resource = resource->next) { 04169 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource); 04170 if (resource->cap) { 04171 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node); 04172 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version); 04173 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 04174 } 04175 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status); 04176 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority); 04177 } 04178 ASTOBJ_UNLOCK(iterator); 04179 }); 04180 iterator = client; 04181 }); 04182 return CLI_SUCCESS; 04183 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4097 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.
04098 { 04099 char *status; 04100 int count = 0; 04101 04102 switch (cmd) { 04103 case CLI_INIT: 04104 e->command = "jabber show connections"; 04105 e->usage = 04106 "Usage: jabber show connections\n" 04107 " Shows state of client and component connections\n"; 04108 return NULL; 04109 case CLI_GENERATE: 04110 return NULL; 04111 } 04112 04113 ast_cli(a->fd, "Jabber Users and their status:\n"); 04114 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04115 ASTOBJ_RDLOCK(iterator); 04116 count++; 04117 switch (iterator->state) { 04118 case AJI_DISCONNECTED: 04119 status = "Disconnected"; 04120 break; 04121 case AJI_CONNECTING: 04122 status = "Connecting"; 04123 break; 04124 case AJI_CONNECTED: 04125 status = "Connected"; 04126 break; 04127 default: 04128 status = "Unknown"; 04129 } 04130 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status); 04131 ASTOBJ_UNLOCK(iterator); 04132 }); 04133 ast_cli(a->fd, "----\n"); 04134 ast_cli(a->fd, " Number of users: %d\n", count); 04135 return CLI_SUCCESS; 04136 }
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 4190 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.
04191 { 04192 struct aji_client *client; 04193 struct aji_resource *resource; 04194 const char *name; 04195 struct aji_message *tmp; 04196 04197 switch (cmd) { 04198 case CLI_INIT: 04199 e->command = "jabber test"; 04200 e->usage = 04201 "Usage: jabber test <connection>\n" 04202 " Sends test message for debugging purposes. A specific client\n" 04203 " as configured in jabber.conf must be specified.\n"; 04204 return NULL; 04205 case CLI_GENERATE: 04206 return NULL; 04207 } 04208 04209 if (a->argc != 3) { 04210 return CLI_SHOWUSAGE; 04211 } 04212 name = a->argv[2]; 04213 04214 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 04215 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 04216 return CLI_FAILURE; 04217 } 04218 04219 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 04220 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 04221 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04222 ASTOBJ_RDLOCK(iterator); 04223 ast_verbose("User: %s\n", iterator->name); 04224 for (resource = iterator->resources; resource; resource = resource->next) { 04225 ast_verbose("Resource: %s\n", resource->resource); 04226 if (resource->cap) { 04227 ast_verbose(" client: %s\n", resource->cap->parent->node); 04228 ast_verbose(" version: %s\n", resource->cap->version); 04229 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 04230 } 04231 ast_verbose(" Priority: %d\n", resource->priority); 04232 ast_verbose(" Status: %d\n", resource->status); 04233 ast_verbose(" Message: %s\n", S_OR(resource->description, "")); 04234 } 04235 ASTOBJ_UNLOCK(iterator); 04236 }); 04237 ast_verbose("\nOooh a working message stack!\n"); 04238 AST_LIST_LOCK(&client->messages); 04239 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 04240 //ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 04241 } 04242 AST_LIST_UNLOCK(&client->messages); 04243 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04244 04245 return CLI_SUCCESS; 04246 }
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 2636 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02637 { 02638 int res = 0; 02639 iks *iq = NULL; 02640 iq = iks_new("iq"); 02641 02642 if (iq && client) { 02643 iks_insert_attrib(iq, "type", "get"); 02644 iks_insert_attrib(iq, "to", server); 02645 iks_insert_attrib(iq, "id", client->mid); 02646 ast_aji_increment_mid(client->mid); 02647 ast_aji_send(client, iq); 02648 } else { 02649 ast_log(LOG_ERROR, "Out of memory.\n"); 02650 } 02651 02652 iks_delete(iq); 02653 02654 return res; 02655 }
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 3143 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().
03144 { 03145 if (client) { 03146 ast_verb(4, "JABBER: Disconnecting\n"); 03147 #ifdef HAVE_OPENSSL 03148 if (client->stream_flags & SECURE) { 03149 SSL_shutdown(client->ssl_session); 03150 SSL_CTX_free(client->ssl_context); 03151 SSL_free(client->ssl_session); 03152 } 03153 #endif 03154 iks_disconnect(client->p); 03155 iks_parser_delete(client->p); 03156 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03157 } 03158 03159 return 1; 03160 }
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 4596 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().
04597 { 04598 struct aji_client *client = NULL; 04599 char *aux = NULL; 04600 04601 client = ASTOBJ_CONTAINER_FIND(&clients, name); 04602 if (!client && strchr(name, '@')) { 04603 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04604 aux = ast_strdupa(iterator->user); 04605 if (strchr(aux, '/')) { 04606 /* strip resource for comparison */ 04607 aux = strsep(&aux, "/"); 04608 } 04609 if (!strncasecmp(aux, name, strlen(aux))) { 04610 client = ASTOBJ_REF(iterator); 04611 } 04612 }); 04613 } 04614 04615 return client; 04616 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) |
Definition at line 4618 of file res_jabber.c.
References clients.
04619 { 04620 return &clients; 04621 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 2780 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().
02781 { 02782 int i = 0; 02783 02784 for (i = strlen(mid) - 1; i >= 0; i--) { 02785 if (mid[i] != 'z') { 02786 mid[i] = mid[i] + 1; 02787 i = 0; 02788 } else 02789 mid[i] = 'a'; 02790 } 02791 }
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 2688 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02689 { 02690 int res = 0; 02691 iks *invite, *body, *namespace; 02692 02693 invite = iks_new("message"); 02694 body = iks_new("body"); 02695 namespace = iks_new("x"); 02696 if (client && invite && body && namespace) { 02697 iks_insert_attrib(invite, "to", user); 02698 iks_insert_attrib(invite, "id", client->mid); 02699 ast_aji_increment_mid(client->mid); 02700 iks_insert_cdata(body, message, 0); 02701 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02702 iks_insert_attrib(namespace, "jid", room); 02703 iks_insert_node(invite, body); 02704 iks_insert_node(invite, namespace); 02705 res = ast_aji_send(client, invite); 02706 } else { 02707 ast_log(LOG_ERROR, "Out of memory.\n"); 02708 } 02709 02710 iks_delete(body); 02711 iks_delete(namespace); 02712 iks_delete(invite); 02713 02714 return res; 02715 }
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 2664 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_join_exec().
02665 { 02666 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL); 02667 }
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 2676 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_leave_exec().
02677 { 02678 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL); 02679 }
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 2572 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().
02573 { 02574 return aji_send_raw_chat(client, 0, NULL, address, message); 02575 }
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 2586 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_sendgroup_exec().
02586 { 02587 return aji_send_raw_chat(client, 1, nick, address, message); 02588 }
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 4750 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.
04751 { 04752 ASTOBJ_CONTAINER_INIT(&clients); 04753 if (!aji_reload(0)) 04754 return AST_MODULE_LOAD_DECLINE; 04755 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 04756 ast_register_application_xml(app_ajisend, aji_send_exec); 04757 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec); 04758 ast_register_application_xml(app_ajistatus, aji_status_exec); 04759 ast_register_application_xml(app_ajijoin, aji_join_exec); 04760 ast_register_application_xml(app_ajileave, aji_leave_exec); 04761 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04762 ast_custom_function_register(&jabberstatus_function); 04763 ast_custom_function_register(&jabberreceive_function); 04764 04765 ast_mutex_init(&messagelock); 04766 ast_cond_init(&message_received_condition, NULL); 04767 return 0; 04768 }
static int manager_jabber_send | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4630 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().
04631 { 04632 struct aji_client *client = NULL; 04633 const char *id = astman_get_header(m, "ActionID"); 04634 const char *jabber = astman_get_header(m, "Jabber"); 04635 const char *screenname = astman_get_header(m, "ScreenName"); 04636 const char *message = astman_get_header(m, "Message"); 04637 04638 if (ast_strlen_zero(jabber)) { 04639 astman_send_error(s, m, "No transport specified"); 04640 return 0; 04641 } 04642 if (ast_strlen_zero(screenname)) { 04643 astman_send_error(s, m, "No ScreenName specified"); 04644 return 0; 04645 } 04646 if (ast_strlen_zero(message)) { 04647 astman_send_error(s, m, "No Message specified"); 04648 return 0; 04649 } 04650 04651 astman_send_ack(s, m, "Attempting to send Jabber Message"); 04652 client = ast_aji_get_client(jabber); 04653 if (!client) { 04654 astman_send_error(s, m, "Could not find Sender"); 04655 return 0; 04656 } 04657 if (strchr(screenname, '@') && message) { 04658 ast_aji_send_chat(client, screenname, message); 04659 astman_append(s, "Response: Success\r\n"); 04660 } else { 04661 astman_append(s, "Response: Error\r\n"); 04662 } 04663 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04664 if (!ast_strlen_zero(id)) { 04665 astman_append(s, "ActionID: %s\r\n", id); 04666 } 04667 astman_append(s, "\r\n"); 04668 return 0; 04669 }
static int reload | ( | void | ) | [static] |
Definition at line 4774 of file res_jabber.c.
References aji_reload().
04775 { 04776 aji_reload(1); 04777 return 0; 04778 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4709 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.
04710 { 04711 04712 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04713 ast_unregister_application(app_ajisend); 04714 ast_unregister_application(app_ajisendgroup); 04715 ast_unregister_application(app_ajistatus); 04716 ast_unregister_application(app_ajijoin); 04717 ast_unregister_application(app_ajileave); 04718 ast_manager_unregister("JabberSend"); 04719 ast_custom_function_unregister(&jabberstatus_function); 04720 if (mwi_sub) { 04721 ast_event_unsubscribe(mwi_sub); 04722 } 04723 if (device_state_sub) { 04724 ast_event_unsubscribe(device_state_sub); 04725 } 04726 ast_custom_function_unregister(&jabberreceive_function); 04727 04728 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04729 ASTOBJ_WRLOCK(iterator); 04730 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 04731 iterator->state = AJI_DISCONNECTING; 04732 ASTOBJ_UNLOCK(iterator); 04733 pthread_join(iterator->thread, NULL); 04734 ast_aji_disconnect(iterator); 04735 }); 04736 04737 ASTOBJ_CONTAINER_DESTROYALL(&clients, ast_aji_client_destroy); 04738 ASTOBJ_CONTAINER_DESTROY(&clients); 04739 04740 ast_cond_destroy(&message_received_condition); 04741 ast_mutex_destroy(&messagelock); 04742 04743 return 0; 04744 }
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 4785 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 4785 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().