A resource for interfacing Asterisk directly as a client or a component to a XMPP/Jabber compliant server. More...
#include "asterisk.h"
#include <ctype.h>
#include <iksemel.h>
#include "asterisk/channel.h"
#include "asterisk/jabber.h"
#include "asterisk/file.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/astobj.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/event.h"
#include "asterisk/devicestate.h"
Go to the source code of this file.
Defines | |
#define | JABBER_CONFIG "jabber.conf" |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | acf_jabberreceive_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
static int | acf_jabberstatus_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen) |
static int | aji_act_hook (void *data, int type, iks *node) |
static iks * | aji_build_node_config (iks *pubsub, const char *node_type, const char *collection_name) |
static iks * | aji_build_node_request (struct aji_client *client, const char *collection) |
Build the a node request. | |
static iks * | aji_build_publish_skeleton (struct aji_client *client, const char *node, const char *event_type, unsigned int cachable) |
Build the skeleton of a publish. | |
static char * | aji_cli_create_collection (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub collection node creation via CLI. | |
static char * | aji_cli_create_leafnode (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub leaf node creation via CLI. | |
static char * | aji_cli_delete_pubsub_node (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub node deletion via CLI. | |
static char * | aji_cli_list_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub node list via CLI. | |
static char * | aji_cli_purge_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to purge PubSub nodes via CLI. | |
static int | aji_client_connect (void *data, ikspak *pak) |
static int | aji_client_info_handler (void *data, ikspak *pak) |
static void | aji_create_affiliations (struct aji_client *client, const char *node) |
Add Owner affiliations for pubsub node. | |
static int | aji_create_buddy (char *label, struct aji_client *client) |
static int | aji_create_client (char *label, struct ast_variable *var, int debug) |
static void | aji_create_pubsub_collection (struct aji_client *client, const char *collection_name) |
Create a PubSub collection node. | |
static void | aji_create_pubsub_leaf (struct aji_client *client, const char *collection_name, const char *leaf_name) |
Create a PubSub leaf node. | |
static iks * | aji_create_pubsub_node (struct aji_client *client, const char *node_type, const char *name, const char *collection_name) |
Create a pubsub node. | |
static int | aji_delete_node_list (void *data, ikspak *pak) |
Delete pubsub item lists. | |
static void | aji_delete_pubsub_node (struct aji_client *client, const char *node_name) |
Delete a PubSub node. | |
static void | aji_devstate_cb (const struct ast_event *ast_event, void *data) |
Callback function for device state events. | |
static int | aji_dinfo_handler (void *data, ikspak *pak) |
static int | aji_ditems_handler (void *data, ikspak *pak) |
static char * | aji_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | aji_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_filter_roster (void *data, ikspak *pak) |
static struct aji_resource * | aji_find_resource (struct aji_buddy *buddy, char *name) |
static struct aji_version * | aji_find_version (char *node, char *version, ikspak *pak) |
static int | aji_get_roster (struct aji_client *client) |
static void | aji_handle_iq (struct aji_client *client, iks *node) |
static void | aji_handle_message (struct aji_client *client, ikspak *pak) |
static void | aji_handle_presence (struct aji_client *client, ikspak *pak) |
static int | aji_handle_pubsub_error (void *data, ikspak *pak) |
static int | aji_handle_pubsub_event (void *data, ikspak *pak) |
Callback for handling PubSub events. | |
static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
static void | aji_init_event_distribution (struct aji_client *client) |
Initialize collections for event distribution. | |
static int | aji_initialize (struct aji_client *client) |
static int | aji_io_recv (struct aji_client *client, char *buffer, size_t buf_len, int timeout) |
static int | aji_is_secure (struct aji_client *client) |
static int | aji_join_exec (struct ast_channel *chan, const char *data) |
Application to join a chat room. | |
static int | aji_leave_exec (struct ast_channel *chan, const char *data) |
Application to leave a chat room. | |
static int | aji_load_config (int reload) |
static void | aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming) |
static void | aji_message_destroy (struct aji_message *obj) |
static void | aji_mwi_cb (const struct ast_event *ast_event, void *data) |
Callback function for MWI events. | |
static void | aji_pruneregister (struct aji_client *client) |
static void | aji_publish_device_state (struct aji_client *client, const char *device, const char *device_state, unsigned int cachable) |
Publish device state to a PubSub node. | |
static void | aji_publish_mwi (struct aji_client *client, const char *mailbox, const char *context, const char *oldmsgs, const char *newmsgs) |
Publish MWI to a PubSub node. | |
static iks * | aji_pubsub_iq_create (struct aji_client *client, const char *type) |
Create an IQ packet. | |
static void | aji_pubsub_purge_nodes (struct aji_client *client, const char *collection_name) |
static void | aji_pubsub_subscribe (struct aji_client *client, const char *node) |
Subscribe to a PubSub node. | |
static int | aji_receive_node_list (void *data, ikspak *pak) |
Receive pubsub item lists. | |
static int | aji_reconnect (struct aji_client *client) |
static int | aji_recv (struct aji_client *client, int timeout) |
static void * | aji_recv_loop (void *data) |
static int | aji_register_approve_handler (void *data, ikspak *pak) |
static int | aji_register_query_handler (void *data, ikspak *pak) |
static int | aji_reload (int reload) |
static void | aji_request_pubsub_nodes (struct aji_client *client, const char *collection) |
Request item list from pubsub. | |
static int | aji_send_exec (struct ast_channel *chan, const char *data) |
static int | aji_send_header (struct aji_client *client, const char *to) |
static int | aji_send_raw (struct aji_client *client, const char *xmlstr) |
static int | aji_send_raw_chat (struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message) |
sends messages. | |
static int | aji_sendgroup_exec (struct ast_channel *chan, const char *data) |
Application to send a message to a groupchat. | |
static int | aji_set_group_presence (struct aji_client *client, char *room, int level, char *nick, char *desc) |
static void | aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc) |
static char * | aji_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | aji_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_start_sasl (struct aji_client *client, enum ikssasltype type, char *username, char *pass) |
static int | aji_start_tls (struct aji_client *client) |
static int | aji_status_exec (struct ast_channel *chan, const char *data) |
static int | aji_tls_handshake (struct aji_client *client) |
void | ast_aji_buddy_destroy (struct aji_buddy *obj) |
void | ast_aji_client_destroy (struct aji_client *obj) |
int | ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic) |
create a chatroom. | |
int | ast_aji_disconnect (struct aji_client *client) |
disconnect from jabber server. | |
struct aji_client * | ast_aji_get_client (const char *name) |
grab a aji_client structure by label name or JID. Bumps the refcount. (without the resource string) | |
struct aji_client_container * | ast_aji_get_clients (void) |
void | ast_aji_increment_mid (char *mid) |
increments the mid field for messages and other events. | |
int | ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message) |
invite to a chatroom. | |
int | ast_aji_join_chat (struct aji_client *client, char *room, char *nick) |
join a chatroom. | |
int | ast_aji_leave_chat (struct aji_client *client, char *room, char *nick) |
leave a chatroom. | |
int | ast_aji_send (struct aji_client *client, iks *x) |
Wraps raw sending. | |
int | ast_aji_send_chat (struct aji_client *client, const char *address, const char *message) |
sends messages. | |
int | ast_aji_send_groupchat (struct aji_client *client, const char *nick, const char *address, const char *message) |
sends message to a groupchat Prior to sending messages to a groupchat, one must be connected to it. | |
static int | delete_old_messages (struct aji_client *client, char *from) |
static int | delete_old_messages_all (struct aji_client *client) |
static int | gtalk_yuck (iks *node) |
static iks * | jabber_make_auth (iksid *id, const char *pass, const char *sid) |
static int | load_module (void) |
static int | manager_jabber_send (struct mansession *s, const struct message *m) |
static int | reload (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "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. |
A resource for interfacing Asterisk directly as a client or a component to a XMPP/Jabber compliant server.
References:
If you unload this module, chan_gtalk/jingle will be dead. How do we handle that?
Dialplan applications need RETURN variable, like JABBERSENDSTATUS
Definition in file res_jabber.c.
#define JABBER_CONFIG "jabber.conf" |
Definition at line 285 of file res_jabber.c.
Referenced by aji_load_config().
static void __reg_module | ( | void | ) | [static] |
Definition at line 4764 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4764 of file res_jabber.c.
static int acf_jabberreceive_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 767 of file res_jabber.c.
References AJI_MAX_JIDLEN, aji_message_destroy(), args, aji_message::arrived, ast_aji_client_destroy(), ast_aji_get_client(), AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_cond_timedwait, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvdiff_sec(), ast_tvnow(), ASTOBJ_UNREF, aji_message::from, LOG_NOTICE, LOG_WARNING, aji_message::message, aji_client::message_timeout, and parse().
00768 { 00769 char *parse = NULL; 00770 int timeout; 00771 int jidlen, resourcelen; 00772 struct timeval start; 00773 long diff = 0; 00774 struct aji_client *client = NULL; 00775 int found = 0; 00776 struct aji_message *tmp = NULL; 00777 AST_DECLARE_APP_ARGS(args, 00778 AST_APP_ARG(account); 00779 AST_APP_ARG(jid); 00780 AST_APP_ARG(timeout); 00781 ); 00782 AST_DECLARE_APP_ARGS(jid, 00783 AST_APP_ARG(screenname); 00784 AST_APP_ARG(resource); 00785 ); 00786 00787 if (ast_strlen_zero(data)) { 00788 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00789 return -1; 00790 } 00791 00792 parse = ast_strdupa(data); 00793 AST_STANDARD_APP_ARGS(args, parse); 00794 00795 if (args.argc < 2 || args.argc > 3) { 00796 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00797 return -1; 00798 } 00799 00800 parse = ast_strdupa(args.jid); 00801 AST_NONSTANDARD_APP_ARGS(jid, parse, '/'); 00802 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) { 00803 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse); 00804 return -1; 00805 } 00806 00807 if (ast_strlen_zero(args.timeout)) { 00808 timeout = 20; 00809 } else { 00810 sscanf(args.timeout, "%d", &timeout); 00811 if (timeout <= 0) { 00812 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 00813 return -1; 00814 } 00815 } 00816 00817 jidlen = strlen(jid.screenname); 00818 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource); 00819 00820 client = ast_aji_get_client(args.account); 00821 if (!client) { 00822 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account); 00823 return -1; 00824 } 00825 00826 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid); 00827 00828 start = ast_tvnow(); 00829 00830 if (chan && ast_autoservice_start(chan) < 0) { 00831 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", chan->name); 00832 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00833 return -1; 00834 } 00835 00836 /* search the messages list, grab the first message that matches with 00837 * the from JID we're expecting, and remove it from the messages list */ 00838 while (diff < timeout) { 00839 struct timespec ts = { 0, }; 00840 struct timeval wait; 00841 int res; 00842 00843 wait = ast_tvadd(start, ast_tv(timeout, 0)); 00844 ts.tv_sec = wait.tv_sec; 00845 ts.tv_nsec = wait.tv_usec * 1000; 00846 00847 /* wait up to timeout seconds for an incoming message */ 00848 ast_mutex_lock(&messagelock); 00849 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts); 00850 ast_mutex_unlock(&messagelock); 00851 if (res == ETIMEDOUT) { 00852 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout); 00853 break; 00854 } 00855 00856 AST_LIST_LOCK(&client->messages); 00857 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00858 if (jid.argc == 1) { 00859 /* no resource provided, compare bare JIDs */ 00860 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00861 continue; 00862 } 00863 } else { 00864 /* resource appended, compare bare JIDs and resources */ 00865 char *resource = strchr(tmp->from, '/'); 00866 if (!resource || strlen(resource) == 0) { 00867 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from); 00868 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00869 continue; 00870 } 00871 } else { 00872 resource ++; 00873 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) { 00874 continue; 00875 } 00876 } 00877 } 00878 /* check if the message is not too old */ 00879 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00880 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from); 00881 AST_LIST_REMOVE_CURRENT(list); 00882 aji_message_destroy(tmp); 00883 continue; 00884 } 00885 found = 1; 00886 ast_copy_string(buf, tmp->message, buflen); 00887 AST_LIST_REMOVE_CURRENT(list); 00888 aji_message_destroy(tmp); 00889 break; 00890 } 00891 AST_LIST_TRAVERSE_SAFE_END; 00892 AST_LIST_UNLOCK(&client->messages); 00893 if (found) { 00894 break; 00895 } 00896 00897 /* check timeout */ 00898 diff = ast_tvdiff_ms(ast_tvnow(), start); 00899 } 00900 00901 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00902 if (chan && ast_autoservice_stop(chan) < 0) { 00903 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", chan->name); 00904 } 00905 00906 /* return if we timed out */ 00907 if (!found) { 00908 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); 00909 return -1; 00910 } 00911 00912 return 0; 00913 }
static int acf_jabberstatus_read | ( | struct ast_channel * | chan, | |
const char * | name, | |||
char * | data, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 696 of file res_jabber.c.
References aji_find_resource(), args, ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_aji_get_client(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, aji_resource::resource, aji_buddy::resources, and aji_resource::status.
00697 { 00698 struct aji_client *client = NULL; 00699 struct aji_buddy *buddy = NULL; 00700 struct aji_resource *r = NULL; 00701 int stat = 7; 00702 AST_DECLARE_APP_ARGS(args, 00703 AST_APP_ARG(sender); 00704 AST_APP_ARG(jid); 00705 ); 00706 AST_DECLARE_APP_ARGS(jid, 00707 AST_APP_ARG(screenname); 00708 AST_APP_ARG(resource); 00709 ); 00710 00711 if (!data) { 00712 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n"); 00713 return 0; 00714 } 00715 AST_STANDARD_APP_ARGS(args, data); 00716 00717 if (args.argc != 2) { 00718 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n"); 00719 return -1; 00720 } 00721 00722 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00723 if (jid.argc < 1 || jid.argc > 2) { 00724 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00725 return -1; 00726 } 00727 00728 if (!(client = ast_aji_get_client(args.sender))) { 00729 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00730 return -1; 00731 } 00732 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00733 if (!buddy) { 00734 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00735 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00736 return -1; 00737 } 00738 r = aji_find_resource(buddy, jid.resource); 00739 if (!r && buddy->resources) { 00740 r = buddy->resources; 00741 } 00742 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00743 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00744 if (!r) { 00745 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00746 } else { 00747 stat = r->status; 00748 } 00749 snprintf(buf, buflen, "%d", stat); 00750 return 0; 00751 }
static int aji_act_hook | ( | void * | data, | |
int | type, | |||
iks * | node | |||
) | [static] |
Definition at line 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(), ast_aji_client_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_asprintf, ast_debug, ast_free, ast_log(), ast_sha1_hash(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::authorized, aji_client::component, aji_client::f, jabber_make_auth(), aji_client::jid, LOG_ERROR, LOG_WARNING, aji_client::mid, aji_client::password, secret, aji_client::state, aji_client::stream_flags, TRY_SECURE, aji_client::usesasl, and aji_client::usetls.
Referenced by aji_create_client().
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 if (ast_asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01723 aji_send_raw(client, handshake); 01724 ast_free(handshake); 01725 } 01726 client->state = AJI_CONNECTING; 01727 if (aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01728 client->state = AJI_CONNECTED; 01729 else 01730 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01731 break; 01732 } 01733 break; 01734 01735 case IKS_NODE_NORMAL: 01736 break; 01737 01738 case IKS_NODE_ERROR: 01739 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01740 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01741 return IKS_HOOK; 01742 01743 case IKS_NODE_STOP: 01744 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01745 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01746 return IKS_HOOK; 01747 } 01748 } 01749 01750 switch (pak->type) { 01751 case IKS_PAK_NONE: 01752 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01753 break; 01754 case IKS_PAK_MESSAGE: 01755 aji_handle_message(client, pak); 01756 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01757 break; 01758 case IKS_PAK_PRESENCE: 01759 aji_handle_presence(client, pak); 01760 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01761 break; 01762 case IKS_PAK_S10N: 01763 aji_handle_subscribe(client, pak); 01764 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01765 break; 01766 case IKS_PAK_IQ: 01767 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01768 aji_handle_iq(client, node); 01769 break; 01770 default: 01771 ast_debug(1, "JABBER: I don't know anything about paktype '%u'\n", pak->type); 01772 break; 01773 } 01774 01775 iks_filter_packet(client->f, pak); 01776 01777 if (node) 01778 iks_delete(node); 01779 01780 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01781 return IKS_OK; 01782 }
static iks * aji_build_node_config | ( | iks * | pubsub, | |
const char * | node_type, | |||
const char * | collection_name | |||
) | [static] |
Definition at line 3856 of file res_jabber.c.
Referenced by aji_create_pubsub_node().
03857 { 03858 iks *configure, *x, *field_owner, *field_node_type, *field_node_config, 03859 *field_deliver_payload, *field_persist_items, *field_access_model, 03860 *field_pubsub_collection; 03861 configure = iks_insert(pubsub, "configure"); 03862 x = iks_insert(configure, "x"); 03863 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03864 iks_insert_attrib(x, "type", "submit"); 03865 field_owner = iks_insert(x, "field"); 03866 iks_insert_attrib(field_owner, "var", "FORM_TYPE"); 03867 iks_insert_attrib(field_owner, "type", "hidden"); 03868 iks_insert_cdata(iks_insert(field_owner, "value"), 03869 "http://jabber.org/protocol/pubsub#owner", 39); 03870 if (node_type) { 03871 field_node_type = iks_insert(x, "field"); 03872 iks_insert_attrib(field_node_type, "var", "pubsub#node_type"); 03873 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type)); 03874 } 03875 field_node_config = iks_insert(x, "field"); 03876 iks_insert_attrib(field_node_config, "var", "FORM_TYPE"); 03877 iks_insert_attrib(field_node_config, "type", "hidden"); 03878 iks_insert_cdata(iks_insert(field_node_config, "value"), 03879 "http://jabber.org/protocol/pubsub#node_config", 45); 03880 field_deliver_payload = iks_insert(x, "field"); 03881 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads"); 03882 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1); 03883 field_persist_items = iks_insert(x, "field"); 03884 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items"); 03885 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1); 03886 field_access_model = iks_insert(x, "field"); 03887 iks_insert_attrib(field_access_model, "var", "pubsub#access_model"); 03888 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9); 03889 if (node_type && !strcasecmp(node_type, "leaf")) { 03890 field_pubsub_collection = iks_insert(x, "field"); 03891 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection"); 03892 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name, 03893 strlen(collection_name)); 03894 } 03895 return configure; 03896 }
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 3586 of file res_jabber.c.
References aji_pubsub_iq_create().
Referenced by aji_pubsub_purge_nodes(), and aji_request_pubsub_nodes().
03587 { 03588 iks *request = aji_pubsub_iq_create(client, "get"); 03589 iks *query; 03590 query = iks_insert(request, "query"); 03591 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 03592 if (collection) { 03593 iks_insert_attrib(query, "node", collection); 03594 } 03595 return request; 03596 }
static iks * aji_build_publish_skeleton | ( | struct aji_client * | client, | |
const char * | node, | |||
const char * | event_type, | |||
unsigned int | cachable | |||
) | [static] |
Build the skeleton of a publish.
client | the configured XMPP client we use to connect to a XMPP server | |
node | Name of the node that will be published to | |
event_type |
Definition at line 3396 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, AST_DEVSTATE_NOT_CACHABLE, and ast_test_flag.
Referenced by aji_publish_device_state(), and aji_publish_mwi().
03398 { 03399 iks *request = aji_pubsub_iq_create(client, "set"); 03400 iks *pubsub, *publish, *item; 03401 pubsub = iks_insert(request, "pubsub"); 03402 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03403 publish = iks_insert(pubsub, "publish"); 03404 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03405 iks_insert_attrib(publish, "node", node); 03406 } else { 03407 iks_insert_attrib(publish, "node", event_type); 03408 } 03409 item = iks_insert(publish, "item"); 03410 iks_insert_attrib(item, "id", node); 03411 03412 if (cachable == AST_DEVSTATE_NOT_CACHABLE) { 03413 iks *options, *x, *field_form_type, *field_persist; 03414 03415 options = iks_insert(pubsub, "publish-options"); 03416 x = iks_insert(options, "x"); 03417 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03418 iks_insert_attrib(x, "type", "submit"); 03419 field_form_type = iks_insert(x, "field"); 03420 iks_insert_attrib(field_form_type, "var", "FORM_TYPE"); 03421 iks_insert_attrib(field_form_type, "type", "hidden"); 03422 iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0); 03423 field_persist = iks_insert(x, "field"); 03424 iks_insert_attrib(field_persist, "var", "pubsub#persist_items"); 03425 iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1); 03426 } 03427 03428 return item; 03429 }
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 3904 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.
03905 { 03906 struct aji_client *client; 03907 const char *name; 03908 const char *collection_name; 03909 03910 switch (cmd) { 03911 case CLI_INIT: 03912 e->command = "jabber create collection"; 03913 e->usage = 03914 "Usage: jabber create collection <connection> <collection>\n" 03915 " Creates a PubSub collection node using the account\n" 03916 " as configured in jabber.conf.\n"; 03917 return NULL; 03918 case CLI_GENERATE: 03919 return NULL; 03920 } 03921 03922 if (a->argc != 5) { 03923 return CLI_SHOWUSAGE; 03924 } 03925 name = a->argv[3]; 03926 collection_name = a->argv[4]; 03927 03928 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03929 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03930 return CLI_FAILURE; 03931 } 03932 03933 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03934 aji_create_pubsub_collection(client, collection_name); 03935 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03936 return CLI_SUCCESS; 03937 }
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 3943 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.
03944 { 03945 struct aji_client *client; 03946 const char *name; 03947 const char *collection_name; 03948 const char *leaf_name; 03949 03950 switch (cmd) { 03951 case CLI_INIT: 03952 e->command = "jabber create leaf"; 03953 e->usage = 03954 "Usage: jabber create leaf <connection> <collection> <leaf>\n" 03955 " Creates a PubSub leaf node using the account\n" 03956 " as configured in jabber.conf.\n"; 03957 return NULL; 03958 case CLI_GENERATE: 03959 return NULL; 03960 } 03961 03962 if (a->argc != 6) { 03963 return CLI_SHOWUSAGE; 03964 } 03965 name = a->argv[3]; 03966 collection_name = a->argv[4]; 03967 leaf_name = a->argv[5]; 03968 03969 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03970 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03971 return CLI_FAILURE; 03972 } 03973 03974 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03975 aji_create_pubsub_leaf(client, collection_name, leaf_name); 03976 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03977 return CLI_SUCCESS; 03978 }
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 3757 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.
03759 { 03760 struct aji_client *client; 03761 const char *name; 03762 03763 switch (cmd) { 03764 case CLI_INIT: 03765 e->command = "jabber delete node"; 03766 e->usage = 03767 "Usage: jabber delete node <connection> <node>\n" 03768 " Deletes a node on PubSub server\n" 03769 " as configured in jabber.conf.\n"; 03770 return NULL; 03771 case CLI_GENERATE: 03772 return NULL; 03773 } 03774 03775 if (a->argc != 5) { 03776 return CLI_SHOWUSAGE; 03777 } 03778 name = a->argv[3]; 03779 03780 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03781 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03782 return CLI_FAILURE; 03783 } 03784 aji_delete_pubsub_node(client, a->argv[4]); 03785 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03786 return CLI_SUCCESS; 03787 }
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 3632 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.
03634 { 03635 struct aji_client *client; 03636 const char *name = NULL; 03637 const char *collection = NULL; 03638 03639 switch (cmd) { 03640 case CLI_INIT: 03641 e->command = "jabber list nodes"; 03642 e->usage = 03643 "Usage: jabber list nodes <connection> [collection]\n" 03644 " Lists the user's nodes on the respective connection\n" 03645 " ([connection] as configured in jabber.conf.)\n"; 03646 return NULL; 03647 case CLI_GENERATE: 03648 return NULL; 03649 } 03650 03651 if (a->argc > 5 || a->argc < 4) { 03652 return CLI_SHOWUSAGE; 03653 } else if (a->argc == 4 || a->argc == 5) { 03654 name = a->argv[3]; 03655 } 03656 if (a->argc == 5) { 03657 collection = a->argv[4]; 03658 } 03659 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03660 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03661 return CLI_FAILURE; 03662 } 03663 03664 ast_cli(a->fd, "Listing pubsub nodes.\n"); 03665 aji_request_pubsub_nodes(client, collection); 03666 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03667 return CLI_SUCCESS; 03668 }
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 3677 of file res_jabber.c.
References aji_delete_pubsub_node(), aji_pubsub_purge_nodes(), AJI_XEP0248, ast_cli_args::argc, ast_cli_args::argv, ast_aji_client_destroy(), ast_cli(), ast_test_flag, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03679 { 03680 struct aji_client *client; 03681 const char *name; 03682 03683 switch (cmd) { 03684 case CLI_INIT: 03685 e->command = "jabber purge nodes"; 03686 e->usage = 03687 "Usage: jabber purge nodes <connection> <node>\n" 03688 " Purges nodes on PubSub server\n" 03689 " as configured in jabber.conf.\n"; 03690 return NULL; 03691 case CLI_GENERATE: 03692 return NULL; 03693 } 03694 03695 if (a->argc != 5) { 03696 return CLI_SHOWUSAGE; 03697 } 03698 name = a->argv[3]; 03699 03700 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03701 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03702 return CLI_FAILURE; 03703 } 03704 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03705 aji_pubsub_purge_nodes(client, a->argv[4]); 03706 } else { 03707 aji_delete_pubsub_node(client, a->argv[4]); 03708 } 03709 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03710 return CLI_SUCCESS; 03711 }
static int aji_client_connect | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3090 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().
03091 { 03092 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03093 int res = IKS_FILTER_PASS; 03094 03095 if (client) { 03096 if (client->state == AJI_DISCONNECTED) { 03097 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); 03098 client->state = AJI_CONNECTING; 03099 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 03100 if (!client->component) { /*client*/ 03101 aji_get_roster(client); 03102 } 03103 if (client->distribute_events) { 03104 aji_init_event_distribution(client); 03105 } 03106 03107 iks_filter_remove_hook(client->f, aji_client_connect); 03108 /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ 03109 res = IKS_FILTER_EAT; 03110 } 03111 } else { 03112 ast_log(LOG_ERROR, "Out of memory.\n"); 03113 } 03114 03115 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03116 return res; 03117 }
static int aji_client_info_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2003 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().
02004 { 02005 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02006 struct aji_resource *resource = NULL; 02007 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02008 02009 if (!buddy) { 02010 ast_log(LOG_NOTICE, "JABBER: Received client info from unknown buddy: %s.\n", pak->from->full); 02011 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02012 return IKS_FILTER_EAT; 02013 } 02014 02015 resource = aji_find_resource(buddy, pak->from->resource); 02016 if (pak->subtype == IKS_TYPE_RESULT) { 02017 if (!resource) { 02018 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02019 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02020 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02021 return IKS_FILTER_EAT; 02022 } 02023 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02024 resource->cap->jingle = 1; 02025 } else { 02026 resource->cap->jingle = 0; 02027 } 02028 } else if (pak->subtype == IKS_TYPE_GET) { 02029 iks *iq, *disco, *ident, *google, *query; 02030 iq = iks_new("iq"); 02031 query = iks_new("query"); 02032 ident = iks_new("identity"); 02033 disco = iks_new("feature"); 02034 google = iks_new("feature"); 02035 if (iq && ident && disco && google) { 02036 iks_insert_attrib(iq, "from", client->jid->full); 02037 iks_insert_attrib(iq, "to", pak->from->full); 02038 iks_insert_attrib(iq, "type", "result"); 02039 iks_insert_attrib(iq, "id", pak->id); 02040 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02041 iks_insert_attrib(ident, "category", "client"); 02042 iks_insert_attrib(ident, "type", "pc"); 02043 iks_insert_attrib(ident, "name", "asterisk"); 02044 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 02045 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 02046 iks_insert_node(iq, query); 02047 iks_insert_node(query, ident); 02048 iks_insert_node(query, google); 02049 iks_insert_node(query, disco); 02050 ast_aji_send(client, iq); 02051 } else { 02052 ast_log(LOG_ERROR, "Out of Memory.\n"); 02053 } 02054 02055 iks_delete(iq); 02056 iks_delete(query); 02057 iks_delete(ident); 02058 iks_delete(google); 02059 iks_delete(disco); 02060 } else if (pak->subtype == IKS_TYPE_ERROR) { 02061 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 02062 } 02063 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02064 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02065 return IKS_FILTER_EAT; 02066 }
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 3332 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().
03333 { 03334 iks *modify_affiliates = aji_pubsub_iq_create(client, "set"); 03335 iks *pubsub, *affiliations, *affiliate; 03336 pubsub = iks_insert(modify_affiliates, "pubsub"); 03337 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03338 affiliations = iks_insert(pubsub, "affiliations"); 03339 iks_insert_attrib(affiliations, "node", node); 03340 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03341 ASTOBJ_RDLOCK(iterator); 03342 affiliate = iks_insert(affiliations, "affiliation"); 03343 iks_insert_attrib(affiliate, "jid", iterator->name); 03344 iks_insert_attrib(affiliate, "affiliation", "owner"); 03345 ASTOBJ_UNLOCK(iterator); 03346 }); 03347 ast_aji_send(client, modify_affiliates); 03348 iks_delete(modify_affiliates); 03349 }
static int aji_create_buddy | ( | char * | label, | |
struct aji_client * | client | |||
) | [static] |
load config file.
Definition at line 4490 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 4236 of file res_jabber.c.
References aji_act_hook(), AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), AJI_PUBSUB, aji_register_approve_handler(), aji_register_query_handler(), ast_aji_client_destroy(), ast_asprintf, ast_calloc, ast_clear_flag, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, ast_free, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_set_flag, ast_test_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::distribute_events, aji_client::f, aji_client::flags, aji_client::forcessl, aji_client::jid, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::mid, ast_variable::name, aji_client::name, aji_client::name_space, ast_variable::next, aji_client::p, aji_client::password, aji_client::port, aji_client::priority, aji_client::pubsub_node, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and ast_variable::value.
Referenced by aji_load_config().
04237 { 04238 char *resource; 04239 struct aji_client *client = NULL; 04240 int flag = 0; 04241 04242 client = ASTOBJ_CONTAINER_FIND(&clients, label); 04243 if (!client) { 04244 flag = 1; 04245 client = ast_calloc(1, sizeof(*client)); 04246 if (!client) { 04247 ast_log(LOG_ERROR, "Out of memory!\n"); 04248 return 0; 04249 } 04250 ASTOBJ_INIT(client); 04251 ASTOBJ_WRLOCK(client); 04252 ASTOBJ_CONTAINER_INIT(&client->buddies); 04253 } else { 04254 ASTOBJ_WRLOCK(client); 04255 ASTOBJ_UNMARK(client); 04256 } 04257 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 04258 ast_copy_string(client->name, label, sizeof(client->name)); 04259 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 04260 04261 /* Set default values for the client object */ 04262 client->debug = debug; 04263 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 04264 client->port = 5222; 04265 client->usetls = 1; 04266 client->usesasl = 1; 04267 client->forcessl = 0; 04268 client->keepalive = 1; 04269 client->timeout = 50; 04270 client->message_timeout = 5; 04271 client->distribute_events = 0; 04272 AST_LIST_HEAD_INIT(&client->messages); 04273 client->component = 0; 04274 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 04275 client->priority = 0; 04276 client->status = IKS_SHOW_AVAILABLE; 04277 04278 if (flag) { 04279 client->authorized = 0; 04280 client->state = AJI_DISCONNECTED; 04281 } 04282 while (var) { 04283 if (!strcasecmp(var->name, "username")) { 04284 ast_copy_string(client->user, var->value, sizeof(client->user)); 04285 } else if (!strcasecmp(var->name, "serverhost")) { 04286 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 04287 } else if (!strcasecmp(var->name, "secret")) { 04288 ast_copy_string(client->password, var->value, sizeof(client->password)); 04289 } else if (!strcasecmp(var->name, "statusmessage")) { 04290 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 04291 } else if (!strcasecmp(var->name, "port")) { 04292 client->port = atoi(var->value); 04293 } else if (!strcasecmp(var->name, "timeout")) { 04294 client->message_timeout = atoi(var->value); 04295 } else if (!strcasecmp(var->name, "debug")) { 04296 client->debug = (ast_false(var->value)) ? 0 : 1; 04297 } else if (!strcasecmp(var->name, "type")) { 04298 if (!strcasecmp(var->value, "component")) { 04299 client->component = 1; 04300 if (client->distribute_events) { 04301 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04302 client->distribute_events = 0; 04303 } 04304 } 04305 } else if (!strcasecmp(var->name, "distribute_events")) { 04306 if (ast_true(var->value)) { 04307 if (client->component) { 04308 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04309 } else { 04310 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) { 04311 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n"); 04312 } else { 04313 ast_set_flag(&pubsubflags, AJI_PUBSUB); 04314 client->distribute_events = 1; 04315 } 04316 } 04317 } 04318 } else if (!strcasecmp(var->name, "pubsub_node")) { 04319 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node)); 04320 } else if (!strcasecmp(var->name, "usetls")) { 04321 client->usetls = (ast_false(var->value)) ? 0 : 1; 04322 } else if (!strcasecmp(var->name, "usesasl")) { 04323 client->usesasl = (ast_false(var->value)) ? 0 : 1; 04324 } else if (!strcasecmp(var->name, "forceoldssl")) { 04325 client->forcessl = (ast_false(var->value)) ? 0 : 1; 04326 } else if (!strcasecmp(var->name, "keepalive")) { 04327 client->keepalive = (ast_false(var->value)) ? 0 : 1; 04328 } else if (!strcasecmp(var->name, "autoprune")) { 04329 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 04330 } else if (!strcasecmp(var->name, "autoregister")) { 04331 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 04332 } else if (!strcasecmp(var->name, "auth_policy")) { 04333 if (!strcasecmp(var->value, "accept")) { 04334 ast_set_flag(&client->flags, AJI_AUTOACCEPT); 04335 } else { 04336 ast_clear_flag(&client->flags, AJI_AUTOACCEPT); 04337 } 04338 } else if (!strcasecmp(var->name, "buddy")) { 04339 aji_create_buddy((char *)var->value, client); 04340 } else if (!strcasecmp(var->name, "priority")) { 04341 client->priority = atoi(var->value); 04342 } else if (!strcasecmp(var->name, "status")) { 04343 if (!strcasecmp(var->value, "unavailable")) { 04344 client->status = IKS_SHOW_UNAVAILABLE; 04345 } else if (!strcasecmp(var->value, "available") 04346 || !strcasecmp(var->value, "online")) { 04347 client->status = IKS_SHOW_AVAILABLE; 04348 } else if (!strcasecmp(var->value, "chat") 04349 || !strcasecmp(var->value, "chatty")) { 04350 client->status = IKS_SHOW_CHAT; 04351 } else if (!strcasecmp(var->value, "away")) { 04352 client->status = IKS_SHOW_AWAY; 04353 } else if (!strcasecmp(var->value, "xa") 04354 || !strcasecmp(var->value, "xaway")) { 04355 client->status = IKS_SHOW_XA; 04356 } else if (!strcasecmp(var->value, "dnd")) { 04357 client->status = IKS_SHOW_DND; 04358 } else if (!strcasecmp(var->value, "invisible")) { 04359 #ifdef IKS_SHOW_INVISIBLE 04360 client->status = IKS_SHOW_INVISIBLE; 04361 #else 04362 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 04363 client->status = IKS_SHOW_DND; 04364 #endif 04365 } else { 04366 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 04367 } 04368 } 04369 /* no transport support in this version */ 04370 /* else if (!strcasecmp(var->name, "transport")) 04371 aji_create_transport(var->value, client); 04372 */ 04373 var = var->next; 04374 } 04375 if (!flag) { 04376 ASTOBJ_UNLOCK(client); 04377 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04378 return 1; 04379 } 04380 04381 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 04382 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 04383 if (!client->p) { 04384 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 04385 return 0; 04386 } 04387 client->stack = iks_stack_new(8192, 8192); 04388 if (!client->stack) { 04389 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 04390 return 0; 04391 } 04392 client->f = iks_filter_new(); 04393 if (!client->f) { 04394 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 04395 return 0; 04396 } 04397 if (!strchr(client->user, '/') && !client->component) { /*client */ 04398 if (ast_asprintf(&resource, "%s/asterisk", client->user) >= 0) { 04399 client->jid = iks_id_new(client->stack, resource); 04400 ast_free(resource); 04401 } 04402 } else { 04403 client->jid = iks_id_new(client->stack, client->user); 04404 } 04405 if (client->component) { 04406 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04407 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 04408 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); 04409 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); 04410 } else { 04411 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04412 } 04413 04414 iks_set_log_hook(client->p, aji_log_hook); 04415 ASTOBJ_UNLOCK(client); 04416 ASTOBJ_CONTAINER_LINK(&clients, client); 04417 return 1; 04418 }
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 3812 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_collection(), and aji_handle_pubsub_error().
03814 { 03815 aji_create_pubsub_node(client, "collection", collection_name, NULL); 03816 }
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 3825 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_leafnode(), and aji_handle_pubsub_error().
03827 { 03828 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name); 03829 }
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 3838 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().
03840 { 03841 iks *node = aji_pubsub_iq_create(client, "set"); 03842 iks *pubsub, *create; 03843 pubsub = iks_insert(node, "pubsub"); 03844 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03845 create = iks_insert(pubsub, "create"); 03846 iks_insert_attrib(create, "node", name); 03847 aji_build_node_config(pubsub, node_type, collection_name); 03848 ast_aji_send(client, node); 03849 aji_create_affiliations(client, name); 03850 iks_delete(node); 03851 return 0; 03852 }
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 3730 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().
03731 { 03732 03733 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03734 iks *item = NULL; 03735 if (iks_has_children(pak->query)) { 03736 item = iks_first_tag(pak->query); 03737 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial, 03738 iks_find_attrib(item, "node")); 03739 while ((item = iks_next_tag(item))) { 03740 aji_delete_pubsub_node(client, iks_find_attrib(item, "node")); 03741 } 03742 } 03743 if (item) { 03744 iks_delete(item); 03745 } 03746 return IKS_FILTER_EAT; 03747 }
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 3795 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().
03796 { 03797 iks *request = aji_pubsub_iq_create(client, "set"); 03798 iks *pubsub, *delete; 03799 pubsub = iks_insert(request, "pubsub"); 03800 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03801 delete = iks_insert(pubsub, "delete"); 03802 iks_insert_attrib(delete, "node", node_name); 03803 ast_aji_send(client, request); 03804 }
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 3209 of file res_jabber.c.
References aji_publish_device_state(), ast_aji_client_destroy(), ast_devstate_str(), ast_eid_cmp(), ast_eid_default, ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_CACHABLE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, and LOG_DEBUG.
Referenced by aji_init_event_distribution().
03210 { 03211 const char *device; 03212 const char *device_state; 03213 unsigned int cachable; 03214 struct aji_client *client; 03215 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03216 { 03217 /* If the event didn't originate from this server, don't send it back out. */ 03218 ast_log(LOG_DEBUG, "Returning here\n"); 03219 return; 03220 } 03221 03222 client = ASTOBJ_REF((struct aji_client *) data); 03223 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); 03224 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); 03225 cachable = ast_event_get_ie_uint(ast_event, AST_EVENT_IE_CACHABLE); 03226 aji_publish_device_state(client, device, device_state, cachable); 03227 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03228 }
static int aji_dinfo_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2075 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().
02076 { 02077 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02078 char *node = NULL; 02079 struct aji_resource *resource = NULL; 02080 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02081 02082 if (!buddy) { 02083 ast_log(LOG_NOTICE, "JABBER: Received client info from unknown buddy: %s.\n", pak->from->full); 02084 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02085 return IKS_FILTER_EAT; 02086 } 02087 02088 if (pak->subtype == IKS_TYPE_ERROR) { 02089 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 02090 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02091 return IKS_FILTER_EAT; 02092 } 02093 resource = aji_find_resource(buddy, pak->from->resource); 02094 if (pak->subtype == IKS_TYPE_RESULT) { 02095 if (!resource) { 02096 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02097 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02098 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02099 return IKS_FILTER_EAT; 02100 } 02101 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02102 resource->cap->jingle = 1; 02103 } else { 02104 resource->cap->jingle = 0; 02105 } 02106 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 02107 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 02108 02109 iq = iks_new("iq"); 02110 query = iks_new("query"); 02111 identity = iks_new("identity"); 02112 disco = iks_new("feature"); 02113 reg = iks_new("feature"); 02114 commands = iks_new("feature"); 02115 gateway = iks_new("feature"); 02116 version = iks_new("feature"); 02117 vcard = iks_new("feature"); 02118 search = iks_new("feature"); 02119 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 02120 iks_insert_attrib(iq, "from", client->user); 02121 iks_insert_attrib(iq, "to", pak->from->full); 02122 iks_insert_attrib(iq, "id", pak->id); 02123 iks_insert_attrib(iq, "type", "result"); 02124 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02125 iks_insert_attrib(identity, "category", "gateway"); 02126 iks_insert_attrib(identity, "type", "pstn"); 02127 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 02128 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 02129 iks_insert_attrib(reg, "var", "jabber:iq:register"); 02130 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 02131 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 02132 iks_insert_attrib(version, "var", "jabber:iq:version"); 02133 iks_insert_attrib(vcard, "var", "vcard-temp"); 02134 iks_insert_attrib(search, "var", "jabber:iq:search"); 02135 02136 iks_insert_node(iq, query); 02137 iks_insert_node(query, identity); 02138 iks_insert_node(query, disco); 02139 iks_insert_node(query, reg); 02140 iks_insert_node(query, commands); 02141 iks_insert_node(query, gateway); 02142 iks_insert_node(query, version); 02143 iks_insert_node(query, vcard); 02144 iks_insert_node(query, search); 02145 ast_aji_send(client, iq); 02146 } else { 02147 ast_log(LOG_ERROR, "Out of memory.\n"); 02148 } 02149 02150 iks_delete(iq); 02151 iks_delete(query); 02152 iks_delete(identity); 02153 iks_delete(disco); 02154 iks_delete(reg); 02155 iks_delete(commands); 02156 iks_delete(gateway); 02157 iks_delete(version); 02158 iks_delete(vcard); 02159 iks_delete(search); 02160 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 02161 iks *iq, *query, *confirm; 02162 iq = iks_new("iq"); 02163 query = iks_new("query"); 02164 confirm = iks_new("item"); 02165 02166 if (iq && query && confirm && client) { 02167 iks_insert_attrib(iq, "from", client->user); 02168 iks_insert_attrib(iq, "to", pak->from->full); 02169 iks_insert_attrib(iq, "id", pak->id); 02170 iks_insert_attrib(iq, "type", "result"); 02171 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 02172 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 02173 iks_insert_attrib(confirm, "node", "confirmaccount"); 02174 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 02175 iks_insert_attrib(confirm, "jid", client->user); 02176 iks_insert_node(iq, query); 02177 iks_insert_node(query, confirm); 02178 ast_aji_send(client, iq); 02179 } else { 02180 ast_log(LOG_ERROR, "Out of memory.\n"); 02181 } 02182 02183 iks_delete(iq); 02184 iks_delete(query); 02185 iks_delete(confirm); 02186 02187 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 02188 iks *iq, *query, *feature; 02189 02190 iq = iks_new("iq"); 02191 query = iks_new("query"); 02192 feature = iks_new("feature"); 02193 02194 if (iq && query && feature && client) { 02195 iks_insert_attrib(iq, "from", client->user); 02196 iks_insert_attrib(iq, "to", pak->from->full); 02197 iks_insert_attrib(iq, "id", pak->id); 02198 iks_insert_attrib(iq, "type", "result"); 02199 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02200 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 02201 iks_insert_node(iq, query); 02202 iks_insert_node(query, feature); 02203 ast_aji_send(client, iq); 02204 } else { 02205 ast_log(LOG_ERROR, "Out of memory.\n"); 02206 } 02207 02208 iks_delete(iq); 02209 iks_delete(query); 02210 iks_delete(feature); 02211 } 02212 02213 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02214 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02215 return IKS_FILTER_EAT; 02216 }
static int aji_ditems_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1906 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().
01907 { 01908 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01909 char *node = NULL; 01910 01911 if (!(node = iks_find_attrib(pak->query, "node"))) { 01912 iks *iq = NULL, *query = NULL, *item = NULL; 01913 iq = iks_new("iq"); 01914 query = iks_new("query"); 01915 item = iks_new("item"); 01916 01917 if (iq && query && item) { 01918 iks_insert_attrib(iq, "from", client->user); 01919 iks_insert_attrib(iq, "to", pak->from->full); 01920 iks_insert_attrib(iq, "id", pak->id); 01921 iks_insert_attrib(iq, "type", "result"); 01922 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01923 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01924 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01925 iks_insert_attrib(item, "jid", client->user); 01926 01927 iks_insert_node(iq, query); 01928 iks_insert_node(query, item); 01929 ast_aji_send(client, iq); 01930 } else { 01931 ast_log(LOG_ERROR, "Out of memory.\n"); 01932 } 01933 01934 iks_delete(iq); 01935 iks_delete(query); 01936 iks_delete(item); 01937 01938 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01939 iks *iq, *query, *confirm; 01940 iq = iks_new("iq"); 01941 query = iks_new("query"); 01942 confirm = iks_new("item"); 01943 if (iq && query && confirm && client) { 01944 iks_insert_attrib(iq, "from", client->user); 01945 iks_insert_attrib(iq, "to", pak->from->full); 01946 iks_insert_attrib(iq, "id", pak->id); 01947 iks_insert_attrib(iq, "type", "result"); 01948 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01949 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01950 iks_insert_attrib(confirm, "node", "confirmaccount"); 01951 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01952 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01953 01954 iks_insert_node(iq, query); 01955 iks_insert_node(query, confirm); 01956 ast_aji_send(client, iq); 01957 } else { 01958 ast_log(LOG_ERROR, "Out of memory.\n"); 01959 } 01960 01961 iks_delete(iq); 01962 iks_delete(query); 01963 iks_delete(confirm); 01964 01965 } else if (!strcasecmp(node, "confirmaccount")) { 01966 iks *iq = NULL, *query = NULL, *feature = NULL; 01967 01968 iq = iks_new("iq"); 01969 query = iks_new("query"); 01970 feature = iks_new("feature"); 01971 01972 if (iq && query && feature && client) { 01973 iks_insert_attrib(iq, "from", client->user); 01974 iks_insert_attrib(iq, "to", pak->from->full); 01975 iks_insert_attrib(iq, "id", pak->id); 01976 iks_insert_attrib(iq, "type", "result"); 01977 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01978 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01979 iks_insert_node(iq, query); 01980 iks_insert_node(query, feature); 01981 ast_aji_send(client, iq); 01982 } else { 01983 ast_log(LOG_ERROR, "Out of memory.\n"); 01984 } 01985 01986 iks_delete(iq); 01987 iks_delete(query); 01988 iks_delete(feature); 01989 } 01990 01991 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01992 return IKS_FILTER_EAT; 01993 01994 }
static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4117 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.
04118 { 04119 switch (cmd) { 04120 case CLI_INIT: 04121 e->command = "jabber reload"; 04122 e->usage = 04123 "Usage: jabber reload\n" 04124 " Reloads the Jabber module.\n"; 04125 return NULL; 04126 case CLI_GENERATE: 04127 return NULL; 04128 } 04129 04130 aji_reload(1); 04131 ast_cli(a->fd, "Jabber Reloaded.\n"); 04132 return CLI_SUCCESS; 04133 }
static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4075 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.
04076 { 04077 switch (cmd) { 04078 case CLI_INIT: 04079 e->command = "jabber set debug {on|off}"; 04080 e->usage = 04081 "Usage: jabber set debug {on|off}\n" 04082 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 04083 return NULL; 04084 case CLI_GENERATE: 04085 return NULL; 04086 } 04087 04088 if (a->argc != e->args) { 04089 return CLI_SHOWUSAGE; 04090 } 04091 04092 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 04093 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04094 ASTOBJ_RDLOCK(iterator); 04095 iterator->debug = 1; 04096 ASTOBJ_UNLOCK(iterator); 04097 }); 04098 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 04099 return CLI_SUCCESS; 04100 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 04101 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04102 ASTOBJ_RDLOCK(iterator); 04103 iterator->debug = 0; 04104 ASTOBJ_UNLOCK(iterator); 04105 }); 04106 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 04107 return CLI_SUCCESS; 04108 } 04109 return CLI_SHOWUSAGE; /* defaults to invalid */ 04110 }
static int aji_filter_roster | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2953 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().
02954 { 02955 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02956 int flag = 0; 02957 iks *x = NULL; 02958 struct aji_buddy *buddy; 02959 02960 client->state = AJI_CONNECTED; 02961 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02962 ASTOBJ_RDLOCK(iterator); 02963 x = iks_child(pak->query); 02964 flag = 0; 02965 while (x) { 02966 if (!iks_strcmp(iks_name(x), "item")) { 02967 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02968 flag = 1; 02969 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02970 } 02971 } 02972 x = iks_next(x); 02973 } 02974 if (!flag) { 02975 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02976 } 02977 iks_delete(x); 02978 02979 ASTOBJ_UNLOCK(iterator); 02980 }); 02981 02982 x = iks_child(pak->query); 02983 while (x) { 02984 flag = 0; 02985 if (iks_strcmp(iks_name(x), "item") == 0) { 02986 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02987 ASTOBJ_RDLOCK(iterator); 02988 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02989 flag = 1; 02990 ASTOBJ_UNLOCK(iterator); 02991 }); 02992 02993 if (flag) { 02994 /* found buddy, don't create a new one */ 02995 x = iks_next(x); 02996 continue; 02997 } 02998 02999 buddy = ast_calloc(1, sizeof(*buddy)); 03000 if (!buddy) { 03001 ast_log(LOG_WARNING, "Out of memory\n"); 03002 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03003 return 0; 03004 } 03005 ASTOBJ_INIT(buddy); 03006 ASTOBJ_WRLOCK(buddy); 03007 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 03008 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 03009 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 03010 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 03011 ASTOBJ_MARK(buddy); 03012 } else if (ast_test_flag(&client->flags, AJI_AUTOREGISTER)) { 03013 if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 03014 /* subscribe to buddy's presence only 03015 if we really need to */ 03016 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 03017 } 03018 } 03019 ASTOBJ_UNLOCK(buddy); 03020 if (buddy) { 03021 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 03022 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 03023 } 03024 } 03025 x = iks_next(x); 03026 } 03027 03028 iks_delete(x); 03029 aji_pruneregister(client); 03030 03031 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03032 return IKS_FILTER_EAT; 03033 }
static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
char * | name | |||
) | [static, read] |
Definition at line 544 of file res_jabber.c.
References aji_resource::next, aji_resource::resource, and aji_buddy::resources.
Referenced by acf_jabberstatus_read(), aji_client_info_handler(), aji_dinfo_handler(), and aji_status_exec().
static struct aji_version* aji_find_version | ( | char * | node, | |
char * | version, | |||
ikspak * | pak | |||
) | [static, read] |
Definition at line 472 of file res_jabber.c.
References ast_copy_string(), ast_free, ast_log(), ast_malloc, aji_version::jingle, LOG_ERROR, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::parent, aji_version::version, and aji_capabilities::versions.
Referenced by aji_handle_presence().
00473 { 00474 struct aji_capabilities *list = NULL; 00475 struct aji_version *res = NULL; 00476 00477 list = capabilities; 00478 00479 if (!node) { 00480 node = pak->from->full; 00481 } 00482 if (!version) { 00483 version = "none supplied."; 00484 } 00485 while (list) { 00486 if (!strcasecmp(list->node, node)) { 00487 res = list->versions; 00488 while(res) { 00489 if (!strcasecmp(res->version, version)) { 00490 return res; 00491 } 00492 res = res->next; 00493 } 00494 /* Specified version not found. Let's add it to 00495 this node in our capabilities list */ 00496 if (!res) { 00497 res = ast_malloc(sizeof(*res)); 00498 if (!res) { 00499 ast_log(LOG_ERROR, "Out of memory!\n"); 00500 return NULL; 00501 } 00502 res->jingle = 0; 00503 res->parent = list; 00504 ast_copy_string(res->version, version, sizeof(res->version)); 00505 res->next = list->versions; 00506 list->versions = res; 00507 return res; 00508 } 00509 } 00510 list = list->next; 00511 } 00512 /* Specified node not found. Let's add it our capabilities list */ 00513 if (!list) { 00514 list = ast_malloc(sizeof(*list)); 00515 if (!list) { 00516 ast_log(LOG_ERROR, "Out of memory!\n"); 00517 return NULL; 00518 } 00519 res = ast_malloc(sizeof(*res)); 00520 if (!res) { 00521 ast_log(LOG_ERROR, "Out of memory!\n"); 00522 ast_free(list); 00523 return NULL; 00524 } 00525 ast_copy_string(list->node, node, sizeof(list->node)); 00526 ast_copy_string(res->version, version, sizeof(res->version)); 00527 res->jingle = 0; 00528 res->parent = list; 00529 res->next = NULL; 00530 list->versions = res; 00531 list->next = capabilities; 00532 capabilities = list; 00533 } 00534 return res; 00535 }
static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Definition at line 3067 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().
03068 { 03069 iks *roster = NULL; 03070 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 03071 03072 if (roster) { 03073 iks_insert_attrib(roster, "id", "roster"); 03074 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 03075 ast_aji_send(client, roster); 03076 } 03077 03078 iks_delete(roster); 03079 03080 return 1; 03081 }
static void aji_handle_iq | ( | struct aji_client * | client, | |
iks * | node | |||
) | [static] |
Definition at line 2225 of file res_jabber.c.
Referenced by aji_act_hook().
static void aji_handle_message | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2237 of file res_jabber.c.
References aji_message::arrived, ast_calloc, ast_cond_broadcast, ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvnow(), delete_old_messages(), aji_message::from, aji_message::id, LOG_ERROR, aji_message::message, and aji_client::name.
Referenced by aji_act_hook().
02238 { 02239 struct aji_message *insert; 02240 int deleted = 0; 02241 02242 ast_debug(3, "client %s received a message\n", client->name); 02243 02244 if (!(insert = ast_calloc(1, sizeof(*insert)))) { 02245 return; 02246 } 02247 02248 insert->arrived = ast_tvnow(); 02249 02250 /* wake up threads waiting for messages */ 02251 ast_mutex_lock(&messagelock); 02252 ast_cond_broadcast(&message_received_condition); 02253 ast_mutex_unlock(&messagelock); 02254 02255 if (iks_find_cdata(pak->x, "body")) { 02256 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 02257 } 02258 if (pak->id) { 02259 ast_copy_string(insert->id, pak->id, sizeof(insert->id)); 02260 } 02261 if (pak->from){ 02262 /* insert will furtherly be added to message list */ 02263 insert->from = ast_strdup(pak->from->full); 02264 if (!insert->from) { 02265 ast_free(insert); 02266 ast_log(LOG_ERROR, "Memory allocation failure\n"); 02267 return; 02268 } 02269 ast_debug(3, "message comes from %s\n", insert->from); 02270 } 02271 02272 /* remove old messages received from this JID 02273 * and insert received message */ 02274 deleted = delete_old_messages(client, pak->from->partial); 02275 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 02276 AST_LIST_LOCK(&client->messages); 02277 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 02278 AST_LIST_UNLOCK(&client->messages); 02279 }
static void aji_handle_presence | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2287 of file res_jabber.c.
References AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_buddy_destroy(), ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_strdup, ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, aji_resource::description, EVENT_FLAG_USER, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, manager_event, aji_client::mid, aji_client::name, aji_resource::next, aji_resource::priority, aji_resource::resource, aji_buddy::resources, S_OR, aji_client::state, aji_resource::status, aji_client::status, status, aji_client::statusmessage, and type.
Referenced by aji_act_hook().
02288 { 02289 int status, priority; 02290 struct aji_buddy *buddy; 02291 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02292 char *ver, *node, *descrip, *type; 02293 02294 if (client->state != AJI_CONNECTED) 02295 aji_create_buddy(pak->from->partial, client); 02296 02297 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02298 if (!buddy && pak->from->partial) { 02299 /* allow our jid to be used to log in with another resource */ 02300 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02301 aji_create_buddy(pak->from->partial, client); 02302 else 02303 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02304 return; 02305 } 02306 type = iks_find_attrib(pak->x, "type"); 02307 if (client->component && type &&!strcasecmp("probe", type)) { 02308 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02309 ast_verbose("what i was looking for \n"); 02310 } 02311 ASTOBJ_WRLOCK(buddy); 02312 status = (pak->show) ? pak->show : 6; 02313 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02314 tmp = buddy->resources; 02315 descrip = ast_strdup(iks_find_cdata(pak->x, "status")); 02316 02317 while (tmp && pak->from->resource) { 02318 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02319 tmp->status = status; 02320 if (tmp->description) { 02321 ast_free(tmp->description); 02322 } 02323 tmp->description = descrip; 02324 found = tmp; 02325 if (status == 6) { /* Sign off Destroy resource */ 02326 if (last && found->next) { 02327 last->next = found->next; 02328 } else if (!last) { 02329 if (found->next) { 02330 buddy->resources = found->next; 02331 } else { 02332 buddy->resources = NULL; 02333 } 02334 } else if (!found->next) { 02335 if (last) { 02336 last->next = NULL; 02337 } else { 02338 buddy->resources = NULL; 02339 } 02340 } 02341 ast_free(found); 02342 found = NULL; 02343 break; 02344 } 02345 /* resource list is sorted by descending priority */ 02346 if (tmp->priority != priority) { 02347 found->priority = priority; 02348 if (!last && !found->next) { 02349 /* resource was found to be unique, 02350 leave loop */ 02351 break; 02352 } 02353 /* search for resource in our list 02354 and take it out for the moment */ 02355 if (last) { 02356 last->next = found->next; 02357 } else { 02358 buddy->resources = found->next; 02359 } 02360 02361 last = NULL; 02362 tmp = buddy->resources; 02363 if (!buddy->resources) { 02364 buddy->resources = found; 02365 } 02366 /* priority processing */ 02367 while (tmp) { 02368 /* insert resource back according to 02369 its priority value */ 02370 if (found->priority > tmp->priority) { 02371 if (last) { 02372 /* insert within list */ 02373 last->next = found; 02374 } 02375 found->next = tmp; 02376 if (!last) { 02377 /* insert on top */ 02378 buddy->resources = found; 02379 } 02380 break; 02381 } 02382 if (!tmp->next) { 02383 /* insert at the end of the list */ 02384 tmp->next = found; 02385 found->next = NULL; 02386 break; 02387 } 02388 last = tmp; 02389 tmp = tmp->next; 02390 } 02391 } 02392 break; 02393 } 02394 last = tmp; 02395 tmp = tmp->next; 02396 } 02397 02398 /* resource not found in our list, create it */ 02399 if (!found && status != 6 && pak->from->resource) { 02400 found = ast_calloc(1, sizeof(*found)); 02401 02402 if (!found) { 02403 ast_log(LOG_ERROR, "Out of memory!\n"); 02404 ASTOBJ_UNLOCK(buddy); 02405 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02406 return; 02407 } 02408 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02409 found->status = status; 02410 found->description = descrip; 02411 found->priority = priority; 02412 found->next = NULL; 02413 last = NULL; 02414 tmp = buddy->resources; 02415 while (tmp) { 02416 if (found->priority > tmp->priority) { 02417 if (last) { 02418 last->next = found; 02419 } 02420 found->next = tmp; 02421 if (!last) { 02422 buddy->resources = found; 02423 } 02424 break; 02425 } 02426 if (!tmp->next) { 02427 tmp->next = found; 02428 break; 02429 } 02430 last = tmp; 02431 tmp = tmp->next; 02432 } 02433 if (!tmp) { 02434 buddy->resources = found; 02435 } 02436 } 02437 02438 ASTOBJ_UNLOCK(buddy); 02439 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02440 02441 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02442 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02443 02444 /* handle gmail client's special caps:c tag */ 02445 if (!node && !ver) { 02446 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02447 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02448 } 02449 02450 /* retrieve capabilites of the new resource */ 02451 if (status != 6 && found && !found->cap) { 02452 found->cap = aji_find_version(node, ver, pak); 02453 if (gtalk_yuck(pak->x)) { /* gtalk should do discover */ 02454 found->cap->jingle = 1; 02455 } 02456 if (found->cap->jingle) { 02457 ast_debug(1, "Special case for google till they support discover.\n"); 02458 } else { 02459 iks *iq, *query; 02460 iq = iks_new("iq"); 02461 query = iks_new("query"); 02462 if (query && iq) { 02463 iks_insert_attrib(iq, "type", "get"); 02464 iks_insert_attrib(iq, "to", pak->from->full); 02465 iks_insert_attrib(iq, "from", client->jid->full); 02466 iks_insert_attrib(iq, "id", client->mid); 02467 ast_aji_increment_mid(client->mid); 02468 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02469 iks_insert_node(iq, query); 02470 ast_aji_send(client, iq); 02471 } else { 02472 ast_log(LOG_ERROR, "Out of memory.\n"); 02473 } 02474 iks_delete(query); 02475 iks_delete(iq); 02476 } 02477 } 02478 switch (pak->subtype) { 02479 case IKS_TYPE_AVAILABLE: 02480 ast_debug(3, "JABBER: I am available ^_* %u\n", pak->subtype); 02481 break; 02482 case IKS_TYPE_UNAVAILABLE: 02483 ast_debug(3, "JABBER: I am unavailable ^_* %u\n", pak->subtype); 02484 break; 02485 default: 02486 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %u\n", pak->subtype); 02487 } 02488 switch (pak->show) { 02489 case IKS_SHOW_UNAVAILABLE: 02490 ast_debug(3, "JABBER: type: %u subtype %u\n", pak->subtype, pak->show); 02491 break; 02492 case IKS_SHOW_AVAILABLE: 02493 ast_debug(3, "JABBER: type is available\n"); 02494 break; 02495 case IKS_SHOW_CHAT: 02496 ast_debug(3, "JABBER: type: %u subtype %u\n", pak->subtype, pak->show); 02497 break; 02498 case IKS_SHOW_AWAY: 02499 ast_debug(3, "JABBER: type is away\n"); 02500 break; 02501 case IKS_SHOW_XA: 02502 ast_debug(3, "JABBER: type: %u subtype %u\n", pak->subtype, pak->show); 02503 break; 02504 case IKS_SHOW_DND: 02505 ast_debug(3, "JABBER: type: %u subtype %u\n", pak->subtype, pak->show); 02506 break; 02507 default: 02508 ast_debug(3, "JABBER: Kinky! how did that happen %u\n", pak->show); 02509 } 02510 02511 if (found) { 02512 manager_event(EVENT_FLAG_USER, "JabberStatus", 02513 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 02514 "\r\nDescription: %s\r\n", 02515 client->name, pak->from->partial, found->resource, found->status, 02516 found->priority, S_OR(found->description, "")); 02517 } else { 02518 manager_event(EVENT_FLAG_USER, "JabberStatus", 02519 "Account: %s\r\nJID: %s\r\nStatus: %u\r\n", 02520 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE); 02521 } 02522 }
static int aji_handle_pubsub_error | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3505 of file res_jabber.c.
References aji_create_pubsub_collection(), aji_create_pubsub_leaf(), aji_create_pubsub_node(), aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_client_destroy(), ast_aji_send(), ast_debug, ast_log(), ast_test_flag, ASTOBJ_REF, ASTOBJ_UNREF, and LOG_ERROR.
Referenced by aji_init_event_distribution().
03506 { 03507 char *node_name; 03508 char *error; 03509 int error_num; 03510 iks *orig_request; 03511 iks *orig_pubsub = iks_find(pak->x, "pubsub"); 03512 struct aji_client *client; 03513 if (!orig_pubsub) { 03514 ast_debug(1, "Error isn't a PubSub error, why are we here?\n"); 03515 return IKS_FILTER_EAT; 03516 } 03517 orig_request = iks_child(orig_pubsub); 03518 error = iks_find_attrib(iks_find(pak->x, "error"), "code"); 03519 node_name = iks_find_attrib(orig_request, "node"); 03520 if (!sscanf(error, "%30d", &error_num)) { 03521 return IKS_FILTER_EAT; 03522 } 03523 if (error_num > 399 && error_num < 500 && error_num != 404) { 03524 ast_log(LOG_ERROR, 03525 "Error performing operation on PubSub node %s, %s.\n", node_name, error); 03526 return IKS_FILTER_EAT; 03527 } else if (error_num > 499 && error_num < 600) { 03528 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error); 03529 return IKS_FILTER_EAT; 03530 } 03531 03532 client = ASTOBJ_REF((struct aji_client *) data); 03533 03534 if (!strcasecmp(iks_name(orig_request), "publish")) { 03535 iks *request; 03536 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03537 if (iks_find(iks_find(orig_request, "item"), "state")) { 03538 aji_create_pubsub_leaf(client, "device_state", node_name); 03539 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) { 03540 aji_create_pubsub_leaf(client, "message_waiting", node_name); 03541 } 03542 } else { 03543 aji_create_pubsub_node(client, NULL, node_name, NULL); 03544 } 03545 request = aji_pubsub_iq_create(client, "set"); 03546 iks_insert_node(request, orig_pubsub); 03547 ast_aji_send(client, request); 03548 iks_delete(request); 03549 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03550 return IKS_FILTER_EAT; 03551 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) { 03552 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03553 aji_create_pubsub_collection(client, node_name); 03554 } else { 03555 aji_create_pubsub_node(client, NULL, node_name, NULL); 03556 } 03557 } 03558 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03559 return IKS_FILTER_EAT; 03560 }
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 3264 of file res_jabber.c.
References AST_DEVSTATE_CACHABLE, ast_devstate_val(), ast_eid_cmp(), ast_eid_default, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CACHABLE, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_RAW, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, AST_EVENT_MWI, ast_event_new(), ast_event_queue(), ast_event_queue_and_cache(), ast_log(), ast_str_to_eid(), LOG_DEBUG, LOG_ERROR, and mailbox.
Referenced by aji_init_event_distribution().
03265 { 03266 char *item_id, *device_state, *mailbox, *cachable_str; 03267 int oldmsgs, newmsgs; 03268 iks *item, *item_content; 03269 struct ast_eid pubsub_eid; 03270 struct ast_event *event; 03271 unsigned int cachable = AST_DEVSTATE_CACHABLE; 03272 03273 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); 03274 if (!item) { 03275 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); 03276 return IKS_FILTER_EAT; 03277 } 03278 item_id = iks_find_attrib(item, "id"); 03279 item_content = iks_child(item); 03280 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid")); 03281 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) { 03282 ast_log(LOG_DEBUG, "Returning here, eid of incoming event matches ours!\n"); 03283 return IKS_FILTER_EAT; 03284 } 03285 if (!strcasecmp(iks_name(item_content), "state")) { 03286 if ((cachable_str = iks_find_attrib(item_content, "cachable"))) { 03287 sscanf(cachable_str, "%30u", &cachable); 03288 } 03289 device_state = iks_find_cdata(item, "state"); 03290 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, 03291 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, 03292 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, 03293 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03294 AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable, 03295 AST_EVENT_IE_END))) { 03296 return IKS_FILTER_EAT; 03297 } 03298 } else if (!strcasecmp(iks_name(item_content), "mailbox")) { 03299 mailbox = strsep(&item_id, "@"); 03300 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs); 03301 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs); 03302 if (!(event = ast_event_new(AST_EVENT_MWI, 03303 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03304 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, item_id, 03305 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, oldmsgs, 03306 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, newmsgs, 03307 AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03308 AST_EVENT_IE_END))) { 03309 return IKS_FILTER_EAT; 03310 } 03311 } else { 03312 ast_log(LOG_DEBUG, "Don't know how to handle PubSub event of type %s\n", 03313 iks_name(item_content)); 03314 return IKS_FILTER_EAT; 03315 } 03316 03317 if (cachable == AST_DEVSTATE_CACHABLE) { 03318 ast_event_queue_and_cache(event); 03319 } else { 03320 ast_event_queue(event); 03321 } 03322 03323 return IKS_FILTER_EAT; 03324 }
static void aji_handle_subscribe | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2531 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().
02532 { 02533 iks *presence = NULL, *status = NULL; 02534 struct aji_buddy* buddy = NULL; 02535 02536 switch (pak->subtype) { 02537 case IKS_TYPE_SUBSCRIBE: 02538 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) { 02539 presence = iks_new("presence"); 02540 status = iks_new("status"); 02541 if (presence && status) { 02542 iks_insert_attrib(presence, "type", "subscribed"); 02543 iks_insert_attrib(presence, "to", pak->from->full); 02544 iks_insert_attrib(presence, "from", client->jid->full); 02545 if (pak->id) 02546 iks_insert_attrib(presence, "id", pak->id); 02547 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02548 iks_insert_node(presence, status); 02549 ast_aji_send(client, presence); 02550 } else { 02551 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02552 } 02553 02554 iks_delete(presence); 02555 iks_delete(status); 02556 } 02557 02558 if (client->component) 02559 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02560 case IKS_TYPE_SUBSCRIBED: 02561 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02562 if (!buddy && pak->from->partial) { 02563 aji_create_buddy(pak->from->partial, client); 02564 } else if (buddy) { 02565 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 02566 } 02567 default: 02568 if (option_verbose > 4) { 02569 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %u\n", pak->subtype); 02570 } 02571 } 02572 }
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 3235 of file res_jabber.c.
References aji_devstate_cb(), aji_handle_pubsub_error(), aji_handle_pubsub_event(), aji_mwi_cb(), aji_pubsub_subscribe(), ast_enable_distributed_devstate(), AST_EVENT_DEVICE_STATE_CHANGE, ast_event_dump_cache(), AST_EVENT_IE_END, AST_EVENT_MWI, ast_event_subscribe(), aji_client::f, and aji_client::pubsub_node.
Referenced by aji_client_connect(), and aji_reload().
03236 { 03237 if (!mwi_sub) { 03238 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription", 03239 client, AST_EVENT_IE_END); 03240 } 03241 if (!device_state_sub) { 03242 if (ast_enable_distributed_devstate()) { 03243 return; 03244 } 03245 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 03246 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END); 03247 ast_event_dump_cache(device_state_sub); 03248 } 03249 03250 aji_pubsub_subscribe(client, "device_state"); 03251 aji_pubsub_subscribe(client, "message_waiting"); 03252 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE, 03253 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE); 03254 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE, 03255 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE); 03256 03257 }
static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 3125 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().
03126 { 03127 int connected = IKS_NET_NOCONN; 03128 03129 #ifdef HAVE_OPENSSL 03130 /* reset stream flags */ 03131 client->stream_flags = 0; 03132 #endif 03133 /* If it's a component, connect to user, otherwise, connect to server */ 03134 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 03135 03136 if (connected == IKS_NET_NOCONN) { 03137 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 03138 return IKS_HOOK; 03139 } else if (connected == IKS_NET_NODNS) { 03140 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, 03141 S_OR(client->serverhost, client->jid->server)); 03142 return IKS_HOOK; 03143 } 03144 03145 return IKS_OK; 03146 }
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 1203 of file res_jabber.c.
References SECURE, and aji_client::stream_flags.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
01204 { 01205 #ifdef HAVE_OPENSSL 01206 return client->stream_flags & SECURE; 01207 #else 01208 return 0; 01209 #endif 01210 }
static int aji_join_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Application to join a chat room.
chan | ast_channel | |
data | Data is sender|jid|nickname. |
0 | success | |
-1 | error |
Definition at line 988 of file res_jabber.c.
References AJI_MAX_RESJIDLEN, args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_join_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, aji_client::component, aji_client::jid, and LOG_ERROR.
Referenced by load_module().
00989 { 00990 struct aji_client *client = NULL; 00991 char *s; 00992 char nick[AJI_MAX_RESJIDLEN]; 00993 00994 AST_DECLARE_APP_ARGS(args, 00995 AST_APP_ARG(sender); 00996 AST_APP_ARG(jid); 00997 AST_APP_ARG(nick); 00998 ); 00999 01000 if (!data) { 01001 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01002 return -1; 01003 } 01004 s = ast_strdupa(data); 01005 01006 AST_STANDARD_APP_ARGS(args, s); 01007 if (args.argc < 2 || args.argc > 3) { 01008 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01009 return -1; 01010 } 01011 01012 if (strchr(args.jid, '/')) { 01013 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n"); 01014 return -1; 01015 } 01016 01017 if (!(client = ast_aji_get_client(args.sender))) { 01018 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01019 return -1; 01020 } 01021 01022 if (!ast_strlen_zero(args.nick)) { 01023 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01024 } else { 01025 if (client->component) { 01026 sprintf(nick, "asterisk"); 01027 } else { 01028 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01029 } 01030 } 01031 01032 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01033 ast_aji_join_chat(client, args.jid, nick); 01034 } else { 01035 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid); 01036 } 01037 01038 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01039 return 0; 01040 }
static int aji_leave_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Application to leave a chat room.
chan | ast_channel | |
data | Data is sender|jid|nickname. |
0 | success | |
-1 | error |
Definition at line 1049 of file res_jabber.c.
References AJI_MAX_RESJIDLEN, args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_leave_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, aji_client::component, aji_client::jid, and LOG_ERROR.
Referenced by load_module().
01050 { 01051 struct aji_client *client = NULL; 01052 char *s; 01053 char nick[AJI_MAX_RESJIDLEN]; 01054 AST_DECLARE_APP_ARGS(args, 01055 AST_APP_ARG(sender); 01056 AST_APP_ARG(jid); 01057 AST_APP_ARG(nick); 01058 ); 01059 01060 if (!data) { 01061 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01062 return -1; 01063 } 01064 s = ast_strdupa(data); 01065 01066 AST_STANDARD_APP_ARGS(args, s); 01067 if (args.argc < 2 || args.argc > 3) { 01068 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave); 01069 return -1; 01070 } 01071 01072 if (strchr(args.jid, '/')) { 01073 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n"); 01074 return -1; 01075 } 01076 01077 if (!(client = ast_aji_get_client(args.sender))) { 01078 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01079 return -1; 01080 } 01081 01082 if (!ast_strlen_zero(args.nick)) { 01083 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01084 } else { 01085 if (client->component) { 01086 sprintf(nick, "asterisk"); 01087 } else { 01088 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01089 } 01090 } 01091 01092 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) { 01093 ast_aji_leave_chat(client, args.jid, nick); 01094 } 01095 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01096 return 0; 01097 }
static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 4517 of file res_jabber.c.
References AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_create_client(), AJI_PUBSUB_AUTOCREATE, AJI_XEP0248, ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, JABBER_CONFIG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_variable::value, and var.
Referenced by aji_reload().
04518 { 04519 char *cat = NULL; 04520 int debug = 0; 04521 struct ast_config *cfg = NULL; 04522 struct ast_variable *var = NULL; 04523 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04524 04525 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 04526 return -1; 04527 } 04528 04529 /* Reset flags to default value */ 04530 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT); 04531 04532 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 04533 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 04534 return 0; 04535 } 04536 04537 cat = ast_category_browse(cfg, NULL); 04538 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 04539 if (!strcasecmp(var->name, "debug")) { 04540 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 04541 } else if (!strcasecmp(var->name, "autoprune")) { 04542 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 04543 } else if (!strcasecmp(var->name, "autoregister")) { 04544 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 04545 } else if (!strcasecmp(var->name, "collection_nodes")) { 04546 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248); 04547 } else if (!strcasecmp(var->name, "pubsub_autocreate")) { 04548 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE); 04549 } else if (!strcasecmp(var->name, "auth_policy")) { 04550 if (!strcasecmp(var->value, "accept")) { 04551 ast_set_flag(&globalflags, AJI_AUTOACCEPT); 04552 } else { 04553 ast_clear_flag(&globalflags, AJI_AUTOACCEPT); 04554 } 04555 } 04556 } 04557 04558 while (cat) { 04559 if (strcasecmp(cat, "general")) { 04560 var = ast_variable_browse(cfg, cat); 04561 aji_create_client(cat, var, debug); 04562 } 04563 cat = ast_category_browse(cfg, cat); 04564 } 04565 ast_config_destroy(cfg); /* or leak memory */ 04566 return 1; 04567 }
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 451 of file res_jabber.c.
References ast_free, aji_message::from, and aji_message::message.
Referenced by acf_jabberreceive_read(), ast_aji_client_destroy(), and delete_old_messages().
static void aji_mwi_cb | ( | const struct ast_event * | ast_event, | |
void * | data | |||
) | [static] |
Callback function for MWI events.
ast_event | ||
data | void pointer to ast_client structure |
Definition at line 3178 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().
03179 { 03180 const char *mailbox; 03181 const char *context; 03182 char oldmsgs[10]; 03183 char newmsgs[10]; 03184 struct aji_client *client; 03185 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03186 { 03187 /* If the event didn't originate from this server, don't send it back out. */ 03188 ast_log(LOG_DEBUG, "Returning here\n"); 03189 return; 03190 } 03191 03192 client = ASTOBJ_REF((struct aji_client *) data); 03193 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX); 03194 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT); 03195 snprintf(oldmsgs, sizeof(oldmsgs), "%u", 03196 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS)); 03197 snprintf(newmsgs, sizeof(newmsgs), "%u", 03198 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS)); 03199 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs); 03200 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03201 03202 }
static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2899 of file res_jabber.c.
References AJI_AUTOPRUNE, ast_aji_send(), ast_log(), ast_test_flag, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, aji_client::buddies, aji_client::jid, and LOG_ERROR.
02900 { 02901 iks *removeiq = iks_new("iq"); 02902 iks *removequery = iks_new("query"); 02903 iks *removeitem = iks_new("item"); 02904 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02905 if (!client || !removeiq || !removequery || !removeitem || !send) { 02906 ast_log(LOG_ERROR, "Out of memory.\n"); 02907 goto safeout; 02908 } 02909 02910 iks_insert_node(removeiq, removequery); 02911 iks_insert_node(removequery, removeitem); 02912 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02913 ASTOBJ_RDLOCK(iterator); 02914 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02915 * be called at the same time */ 02916 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02917 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02918 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02919 " so I am no longer subscribing to your presence.\n")); 02920 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02921 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02922 " your access to my presence.\n")); 02923 iks_insert_attrib(removeiq, "from", client->jid->full); 02924 iks_insert_attrib(removeiq, "type", "set"); 02925 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02926 iks_insert_attrib(removeitem, "jid", iterator->name); 02927 iks_insert_attrib(removeitem, "subscription", "remove"); 02928 ast_aji_send(client, removeiq); 02929 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02930 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02931 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02932 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02933 } 02934 ASTOBJ_UNLOCK(iterator); 02935 }); 02936 02937 safeout: 02938 iks_delete(removeiq); 02939 iks_delete(removequery); 02940 iks_delete(removeitem); 02941 iks_delete(send); 02942 02943 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, ast_aji_buddy_destroy); 02944 }
static void aji_publish_device_state | ( | struct aji_client * | client, | |
const char * | device, | |||
const char * | device_state, | |||
unsigned int | cachable | |||
) | [static] |
Publish device state to a PubSub node.
client | the configured XMPP client we use to connect to a XMPP server | |
device | the name of the device whose state to publish | |
device_state | the state to publish |
Definition at line 3438 of file res_jabber.c.
References aji_build_publish_skeleton(), aji_create_pubsub_node(), AJI_PUBSUB_AUTOCREATE, AJI_XEP0248, ast_aji_send(), ast_eid_default, ast_eid_to_str(), and ast_test_flag.
Referenced by aji_devstate_cb().
03440 { 03441 iks *request = aji_build_publish_skeleton(client, device, "device_state", cachable); 03442 iks *state; 03443 char eid_str[20], cachable_str[2]; 03444 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { 03445 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03446 aji_create_pubsub_node(client, "leaf", device, "device_state"); 03447 } else { 03448 aji_create_pubsub_node(client, NULL, device, NULL); 03449 } 03450 } 03451 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03452 state = iks_insert(request, "state"); 03453 iks_insert_attrib(state, "xmlns", "http://asterisk.org"); 03454 iks_insert_attrib(state, "eid", eid_str); 03455 snprintf(cachable_str, sizeof(cachable_str), "%u", cachable); 03456 iks_insert_attrib(state, "cachable", cachable_str); 03457 iks_insert_cdata(state, device_state, strlen(device_state)); 03458 ast_aji_send(client, iks_root(request)); 03459 iks_delete(request); 03460 }
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 3469 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().
03471 { 03472 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT]; 03473 char eid_str[20]; 03474 iks *mailbox_node, *request; 03475 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); 03476 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting", 1); 03477 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03478 mailbox_node = iks_insert(request, "mailbox"); 03479 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org"); 03480 iks_insert_attrib(mailbox_node, "eid", eid_str); 03481 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs)); 03482 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs)); 03483 ast_aji_send(client, iks_root(request)); 03484 iks_delete(request); 03485 }
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 3493 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().
03494 { 03495 iks *request = iks_new("iq"); 03496 03497 iks_insert_attrib(request, "to", client->pubsub_node); 03498 iks_insert_attrib(request, "from", client->jid->full); 03499 iks_insert_attrib(request, "type", type); 03500 ast_aji_increment_mid(client->mid); 03501 iks_insert_attrib(request, "id", client->mid); 03502 return request; 03503 }
static void aji_pubsub_purge_nodes | ( | struct aji_client * | client, | |
const char * | collection_name | |||
) | [static] |
Definition at line 3713 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().
03714 { 03715 iks *request = aji_build_node_request(client, collection_name); 03716 ast_aji_send(client, request); 03717 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE, 03718 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03719 IKS_RULE_DONE); 03720 ast_aji_send(client, request); 03721 iks_delete(request); 03722 }
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 3357 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_send(), ast_test_flag, and aji_client::jid.
Referenced by aji_init_event_distribution().
03358 { 03359 iks *request = aji_pubsub_iq_create(client, "set"); 03360 iks *pubsub, *subscribe; 03361 03362 pubsub = iks_insert(request, "pubsub"); 03363 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03364 subscribe = iks_insert(pubsub, "subscribe"); 03365 iks_insert_attrib(subscribe, "jid", client->jid->partial); 03366 iks_insert_attrib(subscribe, "node", node); 03367 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03368 iks *options, *x, *sub_options, *sub_type, *sub_depth; 03369 options = iks_insert(pubsub, "options"); 03370 x = iks_insert(options, "x"); 03371 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03372 iks_insert_attrib(x, "type", "submit"); 03373 sub_options = iks_insert(x, "field"); 03374 iks_insert_attrib(sub_options, "var", "FORM_TYPE"); 03375 iks_insert_attrib(sub_options, "type", "hidden"); 03376 iks_insert_cdata(iks_insert(sub_options, "value"), 03377 "http://jabber.org/protocol/pubsub#subscribe_options", 51); 03378 sub_type = iks_insert(x, "field"); 03379 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type"); 03380 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5); 03381 sub_depth = iks_insert(x, "field"); 03382 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth"); 03383 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3); 03384 } 03385 ast_aji_send(client, request); 03386 iks_delete(request); 03387 }
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 3604 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().
03605 { 03606 03607 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03608 iks *item = NULL; 03609 if (iks_has_children(pak->query)) { 03610 item = iks_first_tag(pak->query); 03611 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial, 03612 iks_find_attrib(item, "node")); 03613 while ((item = iks_next_tag(item))) { 03614 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node")); 03615 } 03616 } 03617 if (item) { 03618 iks_delete(item); 03619 } 03620 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03621 return IKS_FILTER_EAT; 03622 }
static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 3041 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().
03042 { 03043 int res = 0; 03044 03045 if (client->state) { 03046 client->state = AJI_DISCONNECTED; 03047 } 03048 client->timeout = 50; 03049 if (client->p) { 03050 iks_parser_reset(client->p); 03051 } 03052 if (client->authorized) { 03053 client->authorized = 0; 03054 } 03055 03056 res = aji_initialize(client); 03057 03058 return res; 03059 }
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 2733 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().
02734 { 02735 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02736 int res = IKS_HOOK; 02737 02738 while (res != IKS_OK) { 02739 ast_debug(3, "JABBER: Connecting.\n"); 02740 res = aji_reconnect(client); 02741 sleep(4); 02742 } 02743 02744 do { 02745 if (res == IKS_NET_RWERR || client->timeout == 0) { 02746 while (res != IKS_OK) { 02747 ast_debug(3, "JABBER: reconnecting.\n"); 02748 res = aji_reconnect(client); 02749 sleep(4); 02750 } 02751 } 02752 02753 res = aji_recv(client, 1); 02754 02755 if (client->state == AJI_DISCONNECTING) { 02756 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02757 pthread_exit(NULL); 02758 } 02759 02760 /* Decrease timeout if no data received, and delete 02761 * old messages globally */ 02762 if (res == IKS_NET_EXPIRED) { 02763 client->timeout--; 02764 delete_old_messages_all(client); 02765 } 02766 if (res == IKS_HOOK) { 02767 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02768 } else if (res == IKS_NET_TLSFAIL) { 02769 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02770 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02771 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02772 if (res == IKS_OK) { 02773 client->timeout = 50; 02774 } else { 02775 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02776 } 02777 } else if (res == IKS_NET_RWERR) { 02778 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02779 } 02780 } while (client); 02781 ASTOBJ_UNREF(client, ast_aji_client_destroy); 02782 return 0; 02783 }
static int aji_register_approve_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1790 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().
01791 { 01792 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01793 iks *iq = NULL, *presence = NULL, *x = NULL; 01794 01795 iq = iks_new("iq"); 01796 presence = iks_new("presence"); 01797 x = iks_new("x"); 01798 if (client && iq && presence && x) { 01799 if (!iks_find(pak->query, "remove")) { 01800 iks_insert_attrib(iq, "from", client->jid->full); 01801 iks_insert_attrib(iq, "to", pak->from->full); 01802 iks_insert_attrib(iq, "id", pak->id); 01803 iks_insert_attrib(iq, "type", "result"); 01804 ast_aji_send(client, iq); 01805 01806 iks_insert_attrib(presence, "from", client->jid->full); 01807 iks_insert_attrib(presence, "to", pak->from->partial); 01808 iks_insert_attrib(presence, "id", client->mid); 01809 ast_aji_increment_mid(client->mid); 01810 iks_insert_attrib(presence, "type", "subscribe"); 01811 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01812 iks_insert_node(presence, x); 01813 ast_aji_send(client, presence); 01814 } 01815 } else { 01816 ast_log(LOG_ERROR, "Out of memory.\n"); 01817 } 01818 01819 iks_delete(iq); 01820 iks_delete(presence); 01821 iks_delete(x); 01822 01823 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01824 return IKS_FILTER_EAT; 01825 }
static int aji_register_query_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1833 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().
01834 { 01835 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01836 struct aji_buddy *buddy = NULL; 01837 char *node = NULL; 01838 iks *iq = NULL, *query = NULL; 01839 01840 client = (struct aji_client *) data; 01841 01842 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01843 if (!buddy) { 01844 iks *error = NULL, *notacceptable = NULL; 01845 01846 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01847 iq = iks_new("iq"); 01848 query = iks_new("query"); 01849 error = iks_new("error"); 01850 notacceptable = iks_new("not-acceptable"); 01851 if (iq && query && error && notacceptable) { 01852 iks_insert_attrib(iq, "type", "error"); 01853 iks_insert_attrib(iq, "from", client->user); 01854 iks_insert_attrib(iq, "to", pak->from->full); 01855 iks_insert_attrib(iq, "id", pak->id); 01856 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01857 iks_insert_attrib(error, "code" , "406"); 01858 iks_insert_attrib(error, "type", "modify"); 01859 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01860 iks_insert_node(iq, query); 01861 iks_insert_node(iq, error); 01862 iks_insert_node(error, notacceptable); 01863 ast_aji_send(client, iq); 01864 } else { 01865 ast_log(LOG_ERROR, "Out of memory.\n"); 01866 } 01867 01868 iks_delete(error); 01869 iks_delete(notacceptable); 01870 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01871 iks *instructions = NULL; 01872 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01873 iq = iks_new("iq"); 01874 query = iks_new("query"); 01875 instructions = iks_new("instructions"); 01876 if (iq && query && instructions && client) { 01877 iks_insert_attrib(iq, "from", client->user); 01878 iks_insert_attrib(iq, "to", pak->from->full); 01879 iks_insert_attrib(iq, "id", pak->id); 01880 iks_insert_attrib(iq, "type", "result"); 01881 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01882 iks_insert_cdata(instructions, explain, 0); 01883 iks_insert_node(iq, query); 01884 iks_insert_node(query, instructions); 01885 ast_aji_send(client, iq); 01886 } else { 01887 ast_log(LOG_ERROR, "Out of memory.\n"); 01888 } 01889 01890 iks_delete(instructions); 01891 } 01892 iks_delete(iq); 01893 iks_delete(query); 01894 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 01895 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01896 return IKS_FILTER_EAT; 01897 }
static int aji_reload | ( | int | reload | ) | [static] |
Definition at line 4654 of file res_jabber.c.
References AJI_CONNECTING, AJI_DISCONNECTED, aji_get_roster(), aji_init_event_distribution(), aji_load_config(), aji_recv_loop(), ast_aji_client_destroy(), ast_log(), ast_pthread_create_background, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, clients, and LOG_ERROR.
Referenced by aji_do_reload(), load_module(), and reload().
04655 { 04656 int res; 04657 04658 ASTOBJ_CONTAINER_MARKALL(&clients); 04659 if (!(res = aji_load_config(reload))) { 04660 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 04661 return 0; 04662 } else if (res == -1) 04663 return 1; 04664 04665 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, ast_aji_client_destroy); 04666 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04667 ASTOBJ_RDLOCK(iterator); 04668 if (iterator->state == AJI_DISCONNECTED) { 04669 if (!iterator->thread) 04670 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 04671 } else if (iterator->state == AJI_CONNECTING) { 04672 aji_get_roster(iterator); 04673 if (iterator->distribute_events) { 04674 aji_init_event_distribution(iterator); 04675 } 04676 } 04677 04678 ASTOBJ_UNLOCK(iterator); 04679 }); 04680 04681 return 1; 04682 }
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 3568 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().
03569 { 03570 iks *request = aji_build_node_request(client, collection); 03571 03572 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE, 03573 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03574 IKS_RULE_DONE); 03575 ast_aji_send(client, request); 03576 iks_delete(request); 03577 03578 }
static int aji_send_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 1107 of file res_jabber.c.
References args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_send_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, and LOG_WARNING.
Referenced by load_module().
01108 { 01109 struct aji_client *client = NULL; 01110 char *s; 01111 AST_DECLARE_APP_ARGS(args, 01112 AST_APP_ARG(sender); 01113 AST_APP_ARG(recipient); 01114 AST_APP_ARG(message); 01115 ); 01116 01117 if (!data) { 01118 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01119 return -1; 01120 } 01121 s = ast_strdupa(data); 01122 01123 AST_STANDARD_APP_ARGS(args, s); 01124 if (args.argc < 3) { 01125 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend); 01126 return -1; 01127 } 01128 01129 if (!(client = ast_aji_get_client(args.sender))) { 01130 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 01131 return -1; 01132 } 01133 if (strchr(args.recipient, '@') && !ast_strlen_zero(args.message)) { 01134 ast_aji_send_chat(client, args.recipient, args.message); 01135 } 01136 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01137 return 0; 01138 }
static int aji_send_header | ( | struct aji_client * | client, | |
const char * | to | |||
) | [static] |
Definition at line 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 2609 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().
02610 { 02611 int res = 0; 02612 iks *message_packet = NULL; 02613 char from[AJI_MAX_JIDLEN]; 02614 /* the nickname is used only in component mode */ 02615 if (nick && client->component) { 02616 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 02617 } else { 02618 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 02619 } 02620 02621 if (client->state != AJI_CONNECTED) { 02622 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02623 return -1; 02624 } 02625 02626 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message); 02627 if (!message_packet) { 02628 ast_log(LOG_ERROR, "Out of memory.\n"); 02629 return -1; 02630 } 02631 iks_insert_attrib(message_packet, "from", from); 02632 res = ast_aji_send(client, message_packet); 02633 iks_delete(message_packet); 02634 02635 return res; 02636 }
static int aji_sendgroup_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Application to send a message to a groupchat.
chan | ast_channel | |
data | Data is sender|groupchat|message. |
0 | success | |
-1 | error |
Definition at line 1147 of file res_jabber.c.
References AJI_MAX_RESJIDLEN, args, ast_aji_client_destroy(), ast_aji_get_client(), ast_aji_send_groupchat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ASTOBJ_UNREF, aji_client::component, aji_client::jid, and LOG_ERROR.
Referenced by load_module().
01148 { 01149 struct aji_client *client = NULL; 01150 char *s; 01151 char nick[AJI_MAX_RESJIDLEN]; 01152 int res = 0; 01153 AST_DECLARE_APP_ARGS(args, 01154 AST_APP_ARG(sender); 01155 AST_APP_ARG(groupchat); 01156 AST_APP_ARG(message); 01157 AST_APP_ARG(nick); 01158 ); 01159 01160 if (!data) { 01161 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01162 return -1; 01163 } 01164 s = ast_strdupa(data); 01165 01166 AST_STANDARD_APP_ARGS(args, s); 01167 if (args.argc < 3 || args.argc > 4) { 01168 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01169 return -1; 01170 } 01171 01172 if (!(client = ast_aji_get_client(args.sender))) { 01173 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01174 return -1; 01175 } 01176 01177 if (ast_strlen_zero(args.nick) || args.argc == 3) { 01178 if (client->component) { 01179 sprintf(nick, "asterisk"); 01180 } else { 01181 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01182 } 01183 } else { 01184 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01185 } 01186 01187 if (strchr(args.groupchat, '@') && !ast_strlen_zero(args.message)) { 01188 res = ast_aji_send_groupchat(client, nick, args.groupchat, args.message); 01189 } 01190 01191 ASTOBJ_UNREF(client, ast_aji_client_destroy); 01192 if (res != IKS_OK) { 01193 return -1; 01194 } 01195 return 0; 01196 }
static int aji_set_group_presence | ( | struct aji_client * | client, | |
char * | room, | |||
int | level, | |||
char * | nick, | |||
char * | desc | |||
) | [static] |
Definition at line 4034 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().
04035 { 04036 int res = 0; 04037 iks *presence = NULL, *x = NULL; 04038 char from[AJI_MAX_JIDLEN]; 04039 char roomid[AJI_MAX_JIDLEN]; 04040 04041 presence = iks_make_pres(level, NULL); 04042 x = iks_new("x"); 04043 04044 if (client->component) { 04045 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 04046 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick); 04047 } else { 04048 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 04049 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user); 04050 } 04051 04052 if (!presence || !x || !client) { 04053 ast_log(LOG_ERROR, "Out of memory.\n"); 04054 res = -1; 04055 goto safeout; 04056 } else { 04057 iks_insert_attrib(presence, "to", roomid); 04058 iks_insert_attrib(presence, "from", from); 04059 iks_insert_attrib(x, "xmlns", MUC_NS); 04060 iks_insert_node(presence, x); 04061 res = ast_aji_send(client, presence); 04062 } 04063 04064 safeout: 04065 iks_delete(presence); 04066 iks_delete(x); 04067 return res; 04068 }
static void aji_set_presence | ( | struct aji_client * | client, | |
char * | to, | |||
char * | from, | |||
int | level, | |||
char * | desc | |||
) | [static] |
Definition at line 3992 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().
03993 { 03994 iks *presence = iks_make_pres(level, desc); 03995 iks *cnode = iks_new("c"); 03996 iks *priority = iks_new("priority"); 03997 char priorityS[10]; 03998 03999 if (presence && cnode && client && priority) { 04000 if (to) { 04001 iks_insert_attrib(presence, "to", to); 04002 } 04003 if (from) { 04004 iks_insert_attrib(presence, "from", from); 04005 } 04006 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 04007 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 04008 iks_insert_node(presence, priority); 04009 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 04010 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 04011 iks_insert_attrib(cnode, "ext", "voice-v1"); 04012 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 04013 iks_insert_node(presence, cnode); 04014 ast_aji_send(client, presence); 04015 } else { 04016 ast_log(LOG_ERROR, "Out of memory.\n"); 04017 } 04018 04019 iks_delete(cnode); 04020 iks_delete(presence); 04021 iks_delete(priority); 04022 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4186 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.
04187 { 04188 struct aji_resource *resource; 04189 struct aji_client *client; 04190 04191 switch (cmd) { 04192 case CLI_INIT: 04193 e->command = "jabber show buddies"; 04194 e->usage = 04195 "Usage: jabber show buddies\n" 04196 " Shows buddy lists of our clients\n"; 04197 return NULL; 04198 case CLI_GENERATE: 04199 return NULL; 04200 } 04201 04202 ast_cli(a->fd, "Jabber buddy lists\n"); 04203 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04204 ast_cli(a->fd, "Client: %s\n", iterator->user); 04205 client = iterator; 04206 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04207 ASTOBJ_RDLOCK(iterator); 04208 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name); 04209 if (!iterator->resources) 04210 ast_cli(a->fd, "\t\tResource: None\n"); 04211 for (resource = iterator->resources; resource; resource = resource->next) { 04212 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource); 04213 if (resource->cap) { 04214 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node); 04215 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version); 04216 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 04217 } 04218 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status); 04219 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority); 04220 } 04221 ASTOBJ_UNLOCK(iterator); 04222 }); 04223 iterator = client; 04224 }); 04225 return CLI_SUCCESS; 04226 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4140 of file res_jabber.c.
References AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.
04141 { 04142 char *status; 04143 int count = 0; 04144 04145 switch (cmd) { 04146 case CLI_INIT: 04147 e->command = "jabber show connections"; 04148 e->usage = 04149 "Usage: jabber show connections\n" 04150 " Shows state of client and component connections\n"; 04151 return NULL; 04152 case CLI_GENERATE: 04153 return NULL; 04154 } 04155 04156 ast_cli(a->fd, "Jabber Users and their status:\n"); 04157 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04158 ASTOBJ_RDLOCK(iterator); 04159 count++; 04160 switch (iterator->state) { 04161 case AJI_DISCONNECTED: 04162 status = "Disconnected"; 04163 break; 04164 case AJI_CONNECTING: 04165 status = "Connecting"; 04166 break; 04167 case AJI_CONNECTED: 04168 status = "Connected"; 04169 break; 04170 default: 04171 status = "Unknown"; 04172 } 04173 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status); 04174 ASTOBJ_UNLOCK(iterator); 04175 }); 04176 ast_cli(a->fd, "----\n"); 04177 ast_cli(a->fd, " Number of users: %d\n", count); 04178 return CLI_SUCCESS; 04179 }
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_alloca, 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 = ast_alloca(len); 01548 base64 = ast_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 1220 of file res_jabber.c.
References aji_client::p, aji_client::stream_flags, and TRY_SECURE.
Referenced by aji_act_hook().
01221 { 01222 int ret; 01223 01224 /* This is sent not encrypted */ 01225 if ((ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"))) { 01226 return ret; 01227 } 01228 01229 client->stream_flags |= TRY_SECURE; 01230 return IKS_OK; 01231 }
static int aji_status_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 620 of file res_jabber.c.
References aji_find_resource(), args, ast_aji_buddy_destroy(), ast_aji_client_destroy(), ast_aji_get_client(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNREF, aji_client::buddies, LOG_ERROR, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), aji_resource::resource, aji_buddy::resources, aji_resource::status, and status.
Referenced by load_module().
00621 { 00622 struct aji_client *client = NULL; 00623 struct aji_buddy *buddy = NULL; 00624 struct aji_resource *r = NULL; 00625 char *s = NULL; 00626 int stat = 7; 00627 char status[2]; 00628 static int deprecation_warning = 0; 00629 AST_DECLARE_APP_ARGS(args, 00630 AST_APP_ARG(sender); 00631 AST_APP_ARG(jid); 00632 AST_APP_ARG(variable); 00633 ); 00634 AST_DECLARE_APP_ARGS(jid, 00635 AST_APP_ARG(screenname); 00636 AST_APP_ARG(resource); 00637 ); 00638 00639 if (deprecation_warning++ % 10 == 0) { 00640 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00641 } 00642 00643 if (!data) { 00644 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00645 return 0; 00646 } 00647 s = ast_strdupa(data); 00648 AST_STANDARD_APP_ARGS(args, s); 00649 00650 if (args.argc != 3) { 00651 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00652 return -1; 00653 } 00654 00655 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00656 if (jid.argc < 1 || jid.argc > 2) { 00657 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00658 return -1; 00659 } 00660 00661 if (!(client = ast_aji_get_client(args.sender))) { 00662 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00663 return -1; 00664 } 00665 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00666 if (!buddy) { 00667 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00668 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00669 return -1; 00670 } 00671 r = aji_find_resource(buddy, jid.resource); 00672 if (!r && buddy->resources) { 00673 r = buddy->resources; 00674 } 00675 ASTOBJ_UNREF(buddy, ast_aji_buddy_destroy); 00676 ASTOBJ_UNREF(client, ast_aji_client_destroy); 00677 if (!r) { 00678 ast_log(LOG_NOTICE, "Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname); 00679 } else { 00680 stat = r->status; 00681 } 00682 snprintf(status, sizeof(status), "%d", stat); 00683 pbx_builtin_setvar_helper(chan, args.variable, status); 00684 return 0; 00685 }
static int aji_tls_handshake | ( | struct aji_client * | client | ) | [static] |
Definition at line 1239 of file res_jabber.c.
References aji_send_header(), ast_debug, aji_client::jid, aji_client::p, SECURE, aji_client::ssl_context, aji_client::ssl_method, aji_client::ssl_session, aji_client::stream_flags, and TRY_SECURE.
Referenced by aji_act_hook().
01240 { 01241 int ret; 01242 int sock; 01243 long ssl_opts; 01244 01245 ast_debug(1, "Starting TLS handshake\n"); 01246 01247 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 01248 client->ssl_method = SSLv23_method(); 01249 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) { 01250 return IKS_NET_TLSFAIL; 01251 } 01252 ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; 01253 SSL_CTX_set_options(client->ssl_context, ssl_opts); 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 432 of file res_jabber.c.
References ast_free, aji_resource::description, aji_resource::next, and aji_buddy::resources.
Referenced by acf_jabberstatus_read(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), aji_handle_presence(), aji_handle_subscribe(), aji_register_query_handler(), aji_status_exec(), ast_aji_client_destroy(), gtalk_alloc(), and jingle_alloc().
00433 { 00434 struct aji_resource *tmp; 00435 00436 while ((tmp = obj->resources)) { 00437 obj->resources = obj->resources->next; 00438 ast_free(tmp->description); 00439 ast_free(tmp); 00440 } 00441 00442 ast_free(obj); 00443 }
void ast_aji_client_destroy | ( | struct aji_client * | obj | ) |
Destructor function for clients to be used with ASTOBJ_UNREF after calls to ast_aji_get_client
Definition at line 410 of file res_jabber.c.
References aji_message_destroy(), ast_aji_buddy_destroy(), ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, aji_client::buddies, aji_client::f, aji_client::p, and aji_client::stack.
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_act_hook(), aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_client_connect(), aji_client_info_handler(), aji_create_client(), aji_devstate_cb(), aji_dinfo_handler(), aji_ditems_handler(), aji_handle_pubsub_error(), aji_join_exec(), aji_leave_exec(), aji_log_hook(), aji_mwi_cb(), aji_receive_node_list(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), ast_aji_disconnect(), gtalk_load_config(), gtalk_newcall(), gtalk_request(), jingle_load_config(), jingle_newcall(), jingle_request(), manager_jabber_send(), and unload_module().
00411 { 00412 struct aji_message *tmp; 00413 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, ast_aji_buddy_destroy); 00414 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00415 iks_filter_delete(obj->f); 00416 iks_parser_delete(obj->p); 00417 iks_stack_delete(obj->stack); 00418 AST_LIST_LOCK(&obj->messages); 00419 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00420 aji_message_destroy(tmp); 00421 } 00422 AST_LIST_HEAD_DESTROY(&obj->messages); 00423 ast_free(obj); 00424 }
int ast_aji_create_chat | ( | struct aji_client * | client, | |
char * | room, | |||
char * | server, | |||
char * | topic | |||
) |
create a chatroom.
client | the configured XMPP client we use to connect to a XMPP server | |
room | name of room | |
server | name of server | |
topic | topic for the room. |
Definition at line 2646 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02647 { 02648 int res = 0; 02649 iks *iq = NULL; 02650 iq = iks_new("iq"); 02651 02652 if (iq && client) { 02653 iks_insert_attrib(iq, "type", "get"); 02654 iks_insert_attrib(iq, "to", server); 02655 iks_insert_attrib(iq, "id", client->mid); 02656 ast_aji_increment_mid(client->mid); 02657 ast_aji_send(client, iq); 02658 } else { 02659 ast_log(LOG_ERROR, "Out of memory.\n"); 02660 } 02661 02662 iks_delete(iq); 02663 02664 return res; 02665 }
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 3153 of file res_jabber.c.
References ast_aji_client_destroy(), ast_verb, ASTOBJ_UNREF, aji_client::p, SECURE, aji_client::ssl_context, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by unload_module().
03154 { 03155 if (client) { 03156 ast_verb(4, "JABBER: Disconnecting\n"); 03157 #ifdef HAVE_OPENSSL 03158 if (client->stream_flags & SECURE) { 03159 SSL_shutdown(client->ssl_session); 03160 SSL_CTX_free(client->ssl_context); 03161 SSL_free(client->ssl_session); 03162 } 03163 #endif 03164 iks_disconnect(client->p); 03165 iks_parser_delete(client->p); 03166 ASTOBJ_UNREF(client, ast_aji_client_destroy); 03167 } 03168 03169 return 1; 03170 }
struct aji_client* ast_aji_get_client | ( | const char * | name | ) | [read] |
grab a aji_client structure by label name or JID. Bumps the refcount. (without the resource string)
name | label or JID |
Definition at line 4575 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_REF, and clients.
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_join_exec(), aji_leave_exec(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), gtalk_create_member(), gtalk_newcall(), gtalk_request(), jingle_create_member(), jingle_newcall(), jingle_request(), and manager_jabber_send().
04576 { 04577 struct aji_client *client = NULL; 04578 char *aux = NULL; 04579 04580 client = ASTOBJ_CONTAINER_FIND(&clients, name); 04581 if (!client && strchr(name, '@')) { 04582 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04583 aux = ast_strdupa(iterator->user); 04584 if (strchr(aux, '/')) { 04585 /* strip resource for comparison */ 04586 aux = strsep(&aux, "/"); 04587 } 04588 if (!strncasecmp(aux, name, strlen(aux))) { 04589 client = ASTOBJ_REF(iterator); 04590 } 04591 }); 04592 } 04593 04594 return client; 04595 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) | [read] |
Definition at line 4597 of file res_jabber.c.
References clients.
Referenced by gtalk_load_config(), and jingle_load_config().
04598 { 04599 return &clients; 04600 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 2790 of file res_jabber.c.
Referenced by aji_act_hook(), aji_handle_presence(), aji_pubsub_iq_create(), aji_register_approve_handler(), ast_aji_create_chat(), ast_aji_invite_chat(), gtalk_action(), gtalk_create_candidates(), gtalk_invite(), jingle_accept_call(), jingle_action(), jingle_create_candidates(), jingle_digit(), and jingle_transmit_invite().
int ast_aji_invite_chat | ( | struct aji_client * | client, | |
char * | user, | |||
char * | room, | |||
char * | message | |||
) |
invite to a chatroom.
Definition at line 2698 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02699 { 02700 int res = 0; 02701 iks *invite, *body, *namespace; 02702 02703 invite = iks_new("message"); 02704 body = iks_new("body"); 02705 namespace = iks_new("x"); 02706 if (client && invite && body && namespace) { 02707 iks_insert_attrib(invite, "to", user); 02708 iks_insert_attrib(invite, "id", client->mid); 02709 ast_aji_increment_mid(client->mid); 02710 iks_insert_cdata(body, message, 0); 02711 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02712 iks_insert_attrib(namespace, "jid", room); 02713 iks_insert_node(invite, body); 02714 iks_insert_node(invite, namespace); 02715 res = ast_aji_send(client, invite); 02716 } else { 02717 ast_log(LOG_ERROR, "Out of memory.\n"); 02718 } 02719 02720 iks_delete(body); 02721 iks_delete(namespace); 02722 iks_delete(invite); 02723 02724 return res; 02725 }
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 2674 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_join_exec().
02675 { 02676 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL); 02677 }
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 2686 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_leave_exec().
02687 { 02688 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL); 02689 }
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 2582 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_send_exec(), gtalk_sendtext(), jingle_sendtext(), and manager_jabber_send().
02583 { 02584 return aji_send_raw_chat(client, 0, NULL, address, message); 02585 }
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 2596 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_sendgroup_exec().
02596 { 02597 return aji_send_raw_chat(client, 1, nick, address, message); 02598 }
static int delete_old_messages | ( | struct aji_client * | client, | |
char * | from | |||
) | [static] |
Definition at line 929 of file res_jabber.c.
References aji_message_destroy(), aji_message::arrived, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_tvdiff_sec(), ast_tvnow(), aji_message::from, LOG_ERROR, and aji_client::message_timeout.
Referenced by aji_handle_message(), and delete_old_messages_all().
00930 { 00931 int deleted = 0; 00932 int isold = 0; 00933 struct aji_message *tmp = NULL; 00934 if (!client) { 00935 ast_log(LOG_ERROR, "Cannot find our XMPP client\n"); 00936 return -1; 00937 } 00938 00939 /* remove old messages */ 00940 AST_LIST_LOCK(&client->messages); 00941 if (AST_LIST_EMPTY(&client->messages)) { 00942 AST_LIST_UNLOCK(&client->messages); 00943 return 0; 00944 } 00945 00946 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00947 if (isold) { 00948 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00949 AST_LIST_REMOVE_CURRENT(list); 00950 aji_message_destroy(tmp); 00951 deleted ++; 00952 } 00953 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00954 isold = 1; 00955 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00956 AST_LIST_REMOVE_CURRENT(list); 00957 aji_message_destroy(tmp); 00958 deleted ++; 00959 } 00960 } 00961 } 00962 AST_LIST_TRAVERSE_SAFE_END; 00963 AST_LIST_UNLOCK(&client->messages); 00964 00965 return deleted; 00966 }
static int delete_old_messages_all | ( | struct aji_client * | client | ) | [static] |
Definition at line 976 of file res_jabber.c.
References delete_old_messages().
Referenced by aji_recv_loop().
00977 { 00978 return delete_old_messages(client, NULL); 00979 }
static int gtalk_yuck | ( | iks * | node | ) | [static] |
Definition at line 566 of file res_jabber.c.
References ast_debug.
Referenced by aji_handle_presence().
00567 { 00568 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) { 00569 ast_debug(1, "Found resource with Googletalk voice capabilities\n"); 00570 return 1; 00571 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) { 00572 ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n"); 00573 return 1; 00574 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) { 00575 ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n"); 00576 return 1; 00577 } 00578 00579 return 0; 00580 }
static iks * jabber_make_auth | ( | iksid * | id, | |
const char * | pass, | |||
const char * | sid | |||
) | [static] |
Definition at line 590 of file res_jabber.c.
References ast_sha1_hash().
Referenced by aji_act_hook().
00591 { 00592 iks *x, *y; 00593 x = iks_new("iq"); 00594 iks_insert_attrib(x, "type", "set"); 00595 y = iks_insert(x, "query"); 00596 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00597 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00598 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00599 if (sid) { 00600 char buf[41]; 00601 char sidpass[100]; 00602 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00603 ast_sha1_hash(buf, sidpass); 00604 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00605 } else { 00606 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00607 } 00608 return x; 00609 }
static int load_module | ( | void | ) | [static] |
Definition at line 4729 of file res_jabber.c.
References aji_join_exec(), aji_leave_exec(), aji_reload(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_cond_init, ast_custom_function_register, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_mutex_init, ast_register_application_xml, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, and manager_jabber_send().
04730 { 04731 ASTOBJ_CONTAINER_INIT(&clients); 04732 if (!aji_reload(0)) 04733 return AST_MODULE_LOAD_DECLINE; 04734 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 04735 ast_register_application_xml(app_ajisend, aji_send_exec); 04736 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec); 04737 ast_register_application_xml(app_ajistatus, aji_status_exec); 04738 ast_register_application_xml(app_ajijoin, aji_join_exec); 04739 ast_register_application_xml(app_ajileave, aji_leave_exec); 04740 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04741 ast_custom_function_register(&jabberstatus_function); 04742 ast_custom_function_register(&jabberreceive_function); 04743 04744 ast_mutex_init(&messagelock); 04745 ast_cond_init(&message_received_condition, NULL); 04746 return 0; 04747 }
static int manager_jabber_send | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4609 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().
04610 { 04611 struct aji_client *client = NULL; 04612 const char *id = astman_get_header(m, "ActionID"); 04613 const char *jabber = astman_get_header(m, "Jabber"); 04614 const char *screenname = astman_get_header(m, "ScreenName"); 04615 const char *message = astman_get_header(m, "Message"); 04616 04617 if (ast_strlen_zero(jabber)) { 04618 astman_send_error(s, m, "No transport specified"); 04619 return 0; 04620 } 04621 if (ast_strlen_zero(screenname)) { 04622 astman_send_error(s, m, "No ScreenName specified"); 04623 return 0; 04624 } 04625 if (ast_strlen_zero(message)) { 04626 astman_send_error(s, m, "No Message specified"); 04627 return 0; 04628 } 04629 04630 astman_send_ack(s, m, "Attempting to send Jabber Message"); 04631 client = ast_aji_get_client(jabber); 04632 if (!client) { 04633 astman_send_error(s, m, "Could not find Sender"); 04634 return 0; 04635 } 04636 if (strchr(screenname, '@') && message) { 04637 ast_aji_send_chat(client, screenname, message); 04638 astman_append(s, "Response: Success\r\n"); 04639 } else { 04640 astman_append(s, "Response: Error\r\n"); 04641 } 04642 ASTOBJ_UNREF(client, ast_aji_client_destroy); 04643 if (!ast_strlen_zero(id)) { 04644 astman_append(s, "ActionID: %s\r\n", id); 04645 } 04646 astman_append(s, "\r\n"); 04647 return 0; 04648 }
static int reload | ( | void | ) | [static] |
Definition at line 4753 of file res_jabber.c.
References aji_reload().
04754 { 04755 aji_reload(1); 04756 return 0; 04757 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4688 of file res_jabber.c.
References AJI_DISCONNECTING, ARRAY_LEN, ast_aji_client_destroy(), ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_custom_function_unregister(), ast_debug, ast_event_unsubscribe(), ast_manager_unregister(), ast_mutex_destroy, ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, and clients.
04689 { 04690 04691 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04692 ast_unregister_application(app_ajisend); 04693 ast_unregister_application(app_ajisendgroup); 04694 ast_unregister_application(app_ajistatus); 04695 ast_unregister_application(app_ajijoin); 04696 ast_unregister_application(app_ajileave); 04697 ast_manager_unregister("JabberSend"); 04698 ast_custom_function_unregister(&jabberstatus_function); 04699 if (mwi_sub) { 04700 ast_event_unsubscribe(mwi_sub); 04701 } 04702 if (device_state_sub) { 04703 ast_event_unsubscribe(device_state_sub); 04704 } 04705 ast_custom_function_unregister(&jabberreceive_function); 04706 04707 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04708 ASTOBJ_WRLOCK(iterator); 04709 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 04710 iterator->state = AJI_DISCONNECTING; 04711 ASTOBJ_UNLOCK(iterator); 04712 pthread_join(iterator->thread, NULL); 04713 ast_aji_disconnect(iterator); 04714 }); 04715 04716 ASTOBJ_CONTAINER_DESTROYALL(&clients, ast_aji_client_destroy); 04717 ASTOBJ_CONTAINER_DESTROY(&clients); 04718 04719 ast_cond_destroy(&message_received_condition); 04720 ast_mutex_destroy(&messagelock); 04721 04722 return 0; 04723 }
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 4764 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
Definition at line 374 of file res_jabber.c.
char* app_ajijoin = "JabberJoin" [static] |
Definition at line 389 of file res_jabber.c.
char* app_ajileave = "JabberLeave" [static] |
Definition at line 390 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 386 of file res_jabber.c.
char* app_ajisendgroup = "JabberSendGroup" [static] |
Definition at line 387 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 388 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4764 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL [static] |
Definition at line 393 of file res_jabber.c.
Referenced by ast_request().
struct aji_client_container clients [static] |
Definition at line 392 of file res_jabber.c.
Referenced by aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_create_client(), aji_do_set_debug(), aji_reload(), aji_show_buddies(), aji_show_clients(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), jingle_load_config(), load_module(), and unload_module().
struct ast_event_sub* device_state_sub = NULL [static] |
Definition at line 395 of file res_jabber.c.
struct ast_flags globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } [static] |
Global flags, initialized to default values.
Definition at line 400 of file res_jabber.c.
struct ast_custom_function jabberreceive_function [static] |
{ .name = "JABBER_RECEIVE", .read = acf_jabberreceive_read, }
Definition at line 915 of file res_jabber.c.
struct ast_custom_function jabberstatus_function [static] |
{ .name = "JABBER_STATUS", .read = acf_jabberstatus_read, }
Definition at line 753 of file res_jabber.c.
ast_cond_t message_received_condition [static] |
Definition at line 396 of file res_jabber.c.
ast_mutex_t messagelock [static] |
Definition at line 397 of file res_jabber.c.
struct ast_event_sub* mwi_sub = NULL [static] |
Definition at line 394 of file res_jabber.c.
struct ast_flags pubsubflags = { 0 } [static] |
PubSub flags, initialized to default values.
Definition at line 403 of file res_jabber.c.