#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 void | aji_buddy_destroy (struct aji_buddy *obj) |
static iks * | aji_build_node_config (iks *pubsub, const char *node_type, const char *collection_name) |
static iks * | aji_build_node_request (struct aji_client *client, const char *collection) |
Build the a node request. | |
static iks * | aji_build_publish_skeleton (struct aji_client *client, const char *node, const char *event_type) |
Build the skeleton of a publish. | |
static char * | aji_cli_create_collection (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub collection node creation via CLI. | |
static char * | aji_cli_create_leafnode (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub leaf node creation via CLI. | |
static char * | aji_cli_delete_pubsub_node (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub node deletion via CLI. | |
static char * | aji_cli_list_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to expose PubSub node list via CLI. | |
static char * | aji_cli_purge_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Method to purge PubSub nodes via CLI. | |
static int | aji_client_connect (void *data, ikspak *pak) |
static void | aji_client_destroy (struct aji_client *obj) |
static int | aji_client_info_handler (void *data, ikspak *pak) |
static void | aji_create_affiliations (struct aji_client *client, const char *node) |
Add Owner affiliations for pubsub node. | |
static int | aji_create_buddy (char *label, struct aji_client *client) |
static int | aji_create_client (char *label, struct ast_variable *var, int debug) |
static void | aji_create_pubsub_collection (struct aji_client *client, const char *collection_name) |
Create a PubSub collection node. | |
static void | aji_create_pubsub_leaf (struct aji_client *client, const char *collection_name, const char *leaf_name) |
Create a PubSub leaf node. | |
static iks * | aji_create_pubsub_node (struct aji_client *client, const char *node_type, const char *name, const char *collection_name) |
Create a pubsub node. | |
static int | aji_delete_node_list (void *data, ikspak *pak) |
Delete pubsub item lists. | |
static void | aji_delete_pubsub_node (struct aji_client *client, const char *node_name) |
Delete a PubSub node. | |
static void | aji_devstate_cb (const struct ast_event *ast_event, void *data) |
Callback function for device state events. | |
static int | aji_dinfo_handler (void *data, ikspak *pak) |
static int | aji_ditems_handler (void *data, ikspak *pak) |
static char * | aji_do_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | aji_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_filter_roster (void *data, ikspak *pak) |
static struct aji_resource * | aji_find_resource (struct aji_buddy *buddy, char *name) |
static struct aji_version * | aji_find_version (char *node, char *version, ikspak *pak) |
static int | aji_get_roster (struct aji_client *client) |
static void | aji_handle_iq (struct aji_client *client, iks *node) |
static void | aji_handle_message (struct aji_client *client, ikspak *pak) |
static void | aji_handle_presence (struct aji_client *client, ikspak *pak) |
static int | aji_handle_pubsub_error (void *data, ikspak *pak) |
static int | aji_handle_pubsub_event (void *data, ikspak *pak) |
Callback for handling PubSub events. | |
static void | aji_handle_subscribe (struct aji_client *client, ikspak *pak) |
static void | aji_init_event_distribution (struct aji_client *client) |
Initialize collections for event distribution. | |
static int | aji_initialize (struct aji_client *client) |
static int | aji_io_recv (struct aji_client *client, char *buffer, size_t buf_len, int timeout) |
static int | aji_is_secure (struct aji_client *client) |
static int | aji_join_exec (struct ast_channel *chan, const char *data) |
Application to join a chat room. | |
static int | aji_leave_exec (struct ast_channel *chan, const char *data) |
Application to leave a chat room. | |
static int | aji_load_config (int reload) |
static void | aji_log_hook (void *data, const char *xmpp, size_t size, int is_incoming) |
static void | aji_message_destroy (struct aji_message *obj) |
static void | aji_mwi_cb (const struct ast_event *ast_event, void *data) |
Callback function for MWI events. | |
static void | aji_pruneregister (struct aji_client *client) |
static void | aji_publish_device_state (struct aji_client *client, const char *device, const char *device_state) |
Publish device state to a PubSub node. | |
static void | aji_publish_mwi (struct aji_client *client, const char *mailbox, const char *context, const char *oldmsgs, const char *newmsgs) |
Publish MWI to a PubSub node. | |
static iks * | aji_pubsub_iq_create (struct aji_client *client, const char *type) |
Create an IQ packet. | |
static void | aji_pubsub_purge_nodes (struct aji_client *client, const char *collection_name) |
static void | aji_pubsub_subscribe (struct aji_client *client, const char *node) |
Subscribe to a PubSub node. | |
static int | aji_receive_node_list (void *data, ikspak *pak) |
Receive pubsub item lists. | |
static int | aji_reconnect (struct aji_client *client) |
static int | aji_recv (struct aji_client *client, int timeout) |
static void * | aji_recv_loop (void *data) |
static int | aji_register_approve_handler (void *data, ikspak *pak) |
static int | aji_register_query_handler (void *data, ikspak *pak) |
static int | aji_reload (int reload) |
static void | aji_request_pubsub_nodes (struct aji_client *client, const char *collection) |
Request item list from pubsub. | |
static int | aji_send_exec (struct ast_channel *chan, const char *data) |
static int | aji_send_header (struct aji_client *client, const char *to) |
static int | aji_send_raw (struct aji_client *client, const char *xmlstr) |
static int | aji_send_raw_chat (struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message) |
sends messages. | |
static int | aji_sendgroup_exec (struct ast_channel *chan, const char *data) |
Application to send a message to a groupchat. | |
static int | aji_set_group_presence (struct aji_client *client, char *room, int level, char *nick, char *desc) |
static void | aji_set_presence (struct aji_client *client, char *to, char *from, int level, char *desc) |
static char * | aji_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | aji_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_start_sasl (struct aji_client *client, enum ikssasltype type, char *username, char *pass) |
static int | aji_start_tls (struct aji_client *client) |
static int | aji_status_exec (struct ast_channel *chan, const char *data) |
static char * | aji_test (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | aji_tls_handshake (struct aji_client *client) |
int | ast_aji_create_chat (struct aji_client *client, char *room, char *server, char *topic) |
create a chatroom. | |
int | ast_aji_disconnect (struct aji_client *client) |
disconnect from jabber server. | |
aji_client * | ast_aji_get_client (const char *name) |
grab a aji_client structure by label name or JID (without the resource string) | |
aji_client_container * | ast_aji_get_clients (void) |
void | ast_aji_increment_mid (char *mid) |
increments the mid field for messages and other events. | |
int | ast_aji_invite_chat (struct aji_client *client, char *user, char *room, char *message) |
invite to a chatroom. | |
int | ast_aji_join_chat (struct aji_client *client, char *room, char *nick) |
join a chatroom. | |
int | ast_aji_leave_chat (struct aji_client *client, char *room, char *nick) |
leave a chatroom. | |
int | ast_aji_send (struct aji_client *client, iks *x) |
Wraps raw sending. | |
int | ast_aji_send_chat (struct aji_client *client, const char *address, const char *message) |
sends messages. | |
int | ast_aji_send_groupchat (struct aji_client *client, const char *nick, const char *address, const char *message) |
sends message to a groupchat Prior to sending messages to a groupchat, one must be connected to it. | |
static int | delete_old_messages (struct aji_client *client, char *from) |
static int | delete_old_messages_all (struct aji_client *client) |
static int | gtalk_yuck (iks *node) |
static iks * | jabber_make_auth (iksid *id, const char *pass, const char *sid) |
static int | load_module (void) |
static int | manager_jabber_send (struct mansession *s, const struct message *m) |
static int | reload (void) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "AJI - Asterisk Jabber Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
static struct ast_cli_entry | aji_cli [] |
static char * | app_ajijoin = "JabberJoin" |
static char * | app_ajileave = "JabberLeave" |
static char * | app_ajisend = "JabberSend" |
static char * | app_ajisendgroup = "JabberSendGroup" |
static char * | app_ajistatus = "JabberStatus" |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct aji_capabilities * | capabilities = NULL |
static struct aji_client_container | clients |
static struct ast_event_sub * | device_state_sub = NULL |
static struct ast_flags | globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } |
Global flags, initialized to default values. | |
static struct ast_custom_function | jabberreceive_function |
static struct ast_custom_function | jabberstatus_function |
static ast_cond_t | message_received_condition |
static ast_mutex_t | messagelock |
static struct ast_event_sub * | mwi_sub = NULL |
static struct ast_flags | pubsubflags = { 0 } |
PubSub flags, initialized to default values. |
References:
Dialplan applications need RETURN variable, like JABBERSENDSTATUS
Definition in file res_jabber.c.
#define JABBER_CONFIG "jabber.conf" |
Definition at line 284 of file res_jabber.c.
Referenced by aji_load_config().
static void __reg_module | ( | void | ) | [static] |
Definition at line 4751 of file res_jabber.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 4751 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 764 of file res_jabber.c.
References aji_client_destroy(), AJI_MAX_JIDLEN, aji_message_destroy(), args, aji_message::arrived, ast_aji_get_client(), AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_cond_timedwait, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvdiff_sec(), ast_tvnow(), ASTOBJ_UNREF, aji_message::from, LOG_NOTICE, LOG_WARNING, aji_message::message, aji_client::message_timeout, messagelock, aji_client::messages, ast_channel::name, and parse().
00765 { 00766 char *aux = NULL, *parse = NULL; 00767 int timeout; 00768 int jidlen, resourcelen; 00769 struct timeval start; 00770 long diff = 0; 00771 struct aji_client *client = NULL; 00772 int found = 0; 00773 struct aji_message *tmp = NULL; 00774 AST_DECLARE_APP_ARGS(args, 00775 AST_APP_ARG(account); 00776 AST_APP_ARG(jid); 00777 AST_APP_ARG(timeout); 00778 ); 00779 AST_DECLARE_APP_ARGS(jid, 00780 AST_APP_ARG(screenname); 00781 AST_APP_ARG(resource); 00782 ); 00783 00784 if (ast_strlen_zero(data)) { 00785 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00786 return -1; 00787 } 00788 00789 parse = ast_strdupa(data); 00790 AST_STANDARD_APP_ARGS(args, parse); 00791 00792 if (args.argc < 2 || args.argc > 3) { 00793 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name); 00794 return -1; 00795 } 00796 00797 client = ast_aji_get_client(args.account); 00798 if (!client) { 00799 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account); 00800 return -1; 00801 } 00802 00803 parse = ast_strdupa(args.jid); 00804 AST_NONSTANDARD_APP_ARGS(jid, parse, '/'); 00805 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > AJI_MAX_JIDLEN) { 00806 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse); 00807 ASTOBJ_UNREF(client, aji_client_destroy); 00808 return -1; 00809 } 00810 00811 if (ast_strlen_zero(args.timeout)) { 00812 timeout = 20; 00813 } else { 00814 sscanf(args.timeout, "%d", &timeout); 00815 if (timeout <= 0) { 00816 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout); 00817 ASTOBJ_UNREF(client, aji_client_destroy); 00818 return -1; 00819 } 00820 } 00821 00822 jidlen = strlen(jid.screenname); 00823 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource); 00824 00825 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid); 00826 00827 start = ast_tvnow(); 00828 00829 if (ast_autoservice_start(chan) < 0) { 00830 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", chan->name); 00831 return -1; 00832 } 00833 00834 /* search the messages list, grab the first message that matches with 00835 * the from JID we're expecting, and remove it from the messages list */ 00836 while (diff < timeout) { 00837 struct timespec ts = { 0, }; 00838 struct timeval wait; 00839 int res; 00840 00841 wait = ast_tvadd(start, ast_tv(timeout, 0)); 00842 ts.tv_sec = wait.tv_sec; 00843 ts.tv_nsec = wait.tv_usec * 1000; 00844 00845 /* wait up to timeout seconds for an incoming message */ 00846 ast_mutex_lock(&messagelock); 00847 res = ast_cond_timedwait(&message_received_condition, &messagelock, &ts); 00848 ast_mutex_unlock(&messagelock); 00849 if (res == ETIMEDOUT) { 00850 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout); 00851 break; 00852 } 00853 00854 AST_LIST_LOCK(&client->messages); 00855 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00856 if (jid.argc == 1) { 00857 /* no resource provided, compare bare JIDs */ 00858 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00859 continue; 00860 } 00861 } else { 00862 /* resource appended, compare bare JIDs and resources */ 00863 char *resource = strchr(tmp->from, '/'); 00864 if (!resource || strlen(resource) == 0) { 00865 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", tmp->from); 00866 if (strncasecmp(jid.screenname, tmp->from, jidlen)) { 00867 continue; 00868 } 00869 } else { 00870 resource ++; 00871 if (strncasecmp(jid.screenname, tmp->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) { 00872 continue; 00873 } 00874 } 00875 } 00876 /* check if the message is not too old */ 00877 if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00878 ast_debug(3, "Found old message from %s, deleting it\n", tmp->from); 00879 AST_LIST_REMOVE_CURRENT(list); 00880 aji_message_destroy(tmp); 00881 continue; 00882 } 00883 found = 1; 00884 aux = ast_strdupa(tmp->message); 00885 AST_LIST_REMOVE_CURRENT(list); 00886 aji_message_destroy(tmp); 00887 break; 00888 } 00889 AST_LIST_TRAVERSE_SAFE_END; 00890 AST_LIST_UNLOCK(&client->messages); 00891 if (found) { 00892 break; 00893 } 00894 00895 /* check timeout */ 00896 diff = ast_tvdiff_ms(ast_tvnow(), start); 00897 } 00898 00899 ASTOBJ_UNREF(client, aji_client_destroy); 00900 if (ast_autoservice_stop(chan) < 0) { 00901 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", chan->name); 00902 } 00903 00904 /* return if we timed out */ 00905 if (!found) { 00906 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid); 00907 return -1; 00908 } 00909 ast_copy_string(buf, aux, buflen); 00910 00911 return 0; 00912 }
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_get_client(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ASTOBJ_CONTAINER_FIND, 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 return -1; 00736 } 00737 r = aji_find_resource(buddy, jid.resource); 00738 if (!r && buddy->resources) { 00739 r = buddy->resources; 00740 } 00741 if (!r) { 00742 ast_log(LOG_NOTICE, "Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname); 00743 } else { 00744 stat = r->status; 00745 } 00746 snprintf(buf, buflen, "%d", stat); 00747 return 0; 00748 }
static int aji_act_hook | ( | void * | data, | |
int | type, | |||
iks * | node | |||
) | [static] |
Definition at line 1568 of file res_jabber.c.
References aji_client_connect(), aji_client_destroy(), AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, AJI_DISCONNECTING, aji_handle_iq(), aji_handle_message(), aji_handle_presence(), aji_handle_subscribe(), aji_is_secure(), AJI_MAX_ATTRLEN, aji_recv(), aji_send_header(), aji_send_raw(), aji_start_sasl(), aji_start_tls(), aji_tls_handshake(), asprintf, ast_aji_increment_mid(), ast_aji_send(), ast_debug, ast_free, ast_log(), ast_sha1_hash(), ASTOBJ_REF, ASTOBJ_UNREF, aji_client::authorized, aji_client::component, aji_client::f, jabber_make_auth(), aji_client::jid, LOG_ERROR, LOG_WARNING, aji_client::mid, aji_client::password, secret, aji_client::state, aji_client::stream_flags, aji_client::usesasl, and aji_client::usetls.
Referenced by aji_create_client().
01569 { 01570 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01571 ikspak *pak = NULL; 01572 iks *auth = NULL; 01573 int features = 0; 01574 01575 if (!node) { 01576 ast_log(LOG_ERROR, "aji_act_hook was called with out a packet\n"); /* most likely cause type is IKS_NODE_ERROR lost connection */ 01577 ASTOBJ_UNREF(client, aji_client_destroy); 01578 return IKS_HOOK; 01579 } 01580 01581 if (client->state == AJI_DISCONNECTING) { 01582 ASTOBJ_UNREF(client, aji_client_destroy); 01583 return IKS_HOOK; 01584 } 01585 01586 pak = iks_packet(node); 01587 01588 /* work around iksemel's impossibility to recognize node names 01589 * containing a semicolon. Set the namespace of the corresponding 01590 * node accordingly. */ 01591 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) { 01592 char *node_ns = NULL; 01593 char attr[AJI_MAX_ATTRLEN]; 01594 char *node_name = iks_name(iks_child(node)); 01595 char *aux = strchr(node_name, ':') + 1; 01596 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name); 01597 node_ns = iks_find_attrib(iks_child(node), attr); 01598 if (node_ns) { 01599 pak->ns = node_ns; 01600 pak->query = iks_child(node); 01601 } 01602 } 01603 01604 01605 if (!client->component) { /*client */ 01606 switch (type) { 01607 case IKS_NODE_START: 01608 if (client->usetls && !aji_is_secure(client)) { 01609 #ifndef HAVE_OPENSSL 01610 ast_log(LOG_ERROR, "OpenSSL not installed. You need to install OpenSSL on this system, or disable the TLS option in your configuration file\n"); 01611 ASTOBJ_UNREF(client, aji_client_destroy); 01612 return IKS_HOOK; 01613 #else 01614 if (aji_start_tls(client) == IKS_NET_TLSFAIL) { 01615 ast_log(LOG_ERROR, "Could not start TLS\n"); 01616 ASTOBJ_UNREF(client, aji_client_destroy); 01617 return IKS_HOOK; 01618 } 01619 #endif 01620 break; 01621 } 01622 if (!client->usesasl) { 01623 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); 01624 auth = jabber_make_auth(client->jid, client->password, iks_find_attrib(node, "id")); 01625 if (auth) { 01626 iks_insert_attrib(auth, "id", client->mid); 01627 iks_insert_attrib(auth, "to", client->jid->server); 01628 ast_aji_increment_mid(client->mid); 01629 ast_aji_send(client, auth); 01630 iks_delete(auth); 01631 } else { 01632 ast_log(LOG_ERROR, "Out of memory.\n"); 01633 } 01634 } 01635 break; 01636 01637 case IKS_NODE_NORMAL: 01638 #ifdef HAVE_OPENSSL 01639 if (client->stream_flags & TRY_SECURE) { 01640 if (!strcmp("proceed", iks_name(node))) { 01641 return aji_tls_handshake(client); 01642 } 01643 } 01644 #endif 01645 if (!strcmp("stream:features", iks_name(node))) { 01646 features = iks_stream_features(node); 01647 if (client->usesasl) { 01648 if (client->usetls && !aji_is_secure(client)) { 01649 break; 01650 } 01651 if (client->authorized) { 01652 if (features & IKS_STREAM_BIND) { 01653 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); 01654 auth = iks_make_resource_bind(client->jid); 01655 if (auth) { 01656 iks_insert_attrib(auth, "id", client->mid); 01657 ast_aji_increment_mid(client->mid); 01658 ast_aji_send(client, auth); 01659 iks_delete(auth); 01660 } else { 01661 ast_log(LOG_ERROR, "Out of memory.\n"); 01662 break; 01663 } 01664 } 01665 if (features & IKS_STREAM_SESSION) { 01666 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); 01667 auth = iks_make_session(); 01668 if (auth) { 01669 iks_insert_attrib(auth, "id", "auth"); 01670 ast_aji_increment_mid(client->mid); 01671 ast_aji_send(client, auth); 01672 iks_delete(auth); 01673 } else { 01674 ast_log(LOG_ERROR, "Out of memory.\n"); 01675 } 01676 } 01677 } else { 01678 int ret; 01679 if (!client->jid->user) { 01680 ast_log(LOG_ERROR, "Malformed Jabber ID : %s (domain missing?)\n", client->jid->full); 01681 break; 01682 } 01683 01684 ret = aji_start_sasl(client, features, client->jid->user, client->password); 01685 if (ret != IKS_OK) { 01686 ASTOBJ_UNREF(client, aji_client_destroy); 01687 return IKS_HOOK; 01688 } 01689 break; 01690 } 01691 } 01692 } else if (!strcmp("failure", iks_name(node))) { 01693 ast_log(LOG_ERROR, "JABBER: encryption failure. possible bad password.\n"); 01694 } else if (!strcmp("success", iks_name(node))) { 01695 client->authorized = 1; 01696 aji_send_header(client, client->jid->server); 01697 } 01698 break; 01699 case IKS_NODE_ERROR: 01700 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01701 ASTOBJ_UNREF(client, aji_client_destroy); 01702 return IKS_HOOK; 01703 break; 01704 case IKS_NODE_STOP: 01705 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01706 ASTOBJ_UNREF(client, aji_client_destroy); 01707 return IKS_HOOK; 01708 break; 01709 } 01710 } else if (client->state != AJI_CONNECTED && client->component) { 01711 switch (type) { 01712 case IKS_NODE_START: 01713 if (client->state == AJI_DISCONNECTED) { 01714 char secret[160], shasum[320], *handshake; 01715 01716 sprintf(secret, "%s%s", pak->id, client->password); 01717 ast_sha1_hash(shasum, secret); 01718 handshake = NULL; 01719 if (asprintf(&handshake, "<handshake>%s</handshake>", shasum) >= 0) { 01720 aji_send_raw(client, handshake); 01721 ast_free(handshake); 01722 handshake = NULL; 01723 } 01724 client->state = AJI_CONNECTING; 01725 if (aji_recv(client, 1) == 2) /*XXX proper result for iksemel library on iks_recv of <handshake/> XXX*/ 01726 client->state = AJI_CONNECTED; 01727 else 01728 ast_log(LOG_WARNING, "Jabber didn't seem to handshake, failed to authenticate.\n"); 01729 break; 01730 } 01731 break; 01732 01733 case IKS_NODE_NORMAL: 01734 break; 01735 01736 case IKS_NODE_ERROR: 01737 ast_log(LOG_ERROR, "JABBER: Node Error\n"); 01738 ASTOBJ_UNREF(client, aji_client_destroy); 01739 return IKS_HOOK; 01740 01741 case IKS_NODE_STOP: 01742 ast_log(LOG_WARNING, "JABBER: Disconnected\n"); 01743 ASTOBJ_UNREF(client, aji_client_destroy); 01744 return IKS_HOOK; 01745 } 01746 } 01747 01748 switch (pak->type) { 01749 case IKS_PAK_NONE: 01750 ast_debug(1, "JABBER: I don't know what to do with paktype NONE.\n"); 01751 break; 01752 case IKS_PAK_MESSAGE: 01753 aji_handle_message(client, pak); 01754 ast_debug(1, "JABBER: Handling paktype MESSAGE.\n"); 01755 break; 01756 case IKS_PAK_PRESENCE: 01757 aji_handle_presence(client, pak); 01758 ast_debug(1, "JABBER: Handling paktype PRESENCE\n"); 01759 break; 01760 case IKS_PAK_S10N: 01761 aji_handle_subscribe(client, pak); 01762 ast_debug(1, "JABBER: Handling paktype S10N\n"); 01763 break; 01764 case IKS_PAK_IQ: 01765 ast_debug(1, "JABBER: Handling paktype IQ\n"); 01766 aji_handle_iq(client, node); 01767 break; 01768 default: 01769 ast_debug(1, "JABBER: I don't know anything about paktype '%d'\n", pak->type); 01770 break; 01771 } 01772 01773 iks_filter_packet(client->f, pak); 01774 01775 if (node) 01776 iks_delete(node); 01777 01778 ASTOBJ_UNREF(client, aji_client_destroy); 01779 return IKS_OK; 01780 }
static void aji_buddy_destroy | ( | struct aji_buddy * | obj | ) | [static] |
Definition at line 435 of file res_jabber.c.
References ast_free, aji_resource::description, aji_resource::next, and aji_buddy::resources.
Referenced by aji_client_destroy(), aji_create_buddy(), and aji_handle_presence().
00436 { 00437 struct aji_resource *tmp; 00438 00439 while ((tmp = obj->resources)) { 00440 obj->resources = obj->resources->next; 00441 ast_free(tmp->description); 00442 ast_free(tmp); 00443 } 00444 00445 ast_free(obj); 00446 }
static iks * aji_build_node_config | ( | iks * | pubsub, | |
const char * | node_type, | |||
const char * | collection_name | |||
) | [static] |
Definition at line 3791 of file res_jabber.c.
Referenced by aji_create_pubsub_node().
03792 { 03793 iks *configure, *x, *field_owner, *field_node_type, *field_node_config, 03794 *field_deliver_payload, *field_persist_items, *field_access_model, 03795 *field_pubsub_collection; 03796 configure = iks_insert(pubsub, "configure"); 03797 x = iks_insert(configure, "x"); 03798 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03799 iks_insert_attrib(x, "type", "submit"); 03800 field_owner = iks_insert(x, "field"); 03801 iks_insert_attrib(field_owner, "var", "FORM_TYPE"); 03802 iks_insert_attrib(field_owner, "type", "hidden"); 03803 iks_insert_cdata(iks_insert(field_owner, "value"), 03804 "http://jabber.org/protocol/pubsub#owner", 39); 03805 if (node_type) { 03806 field_node_type = iks_insert(x, "field"); 03807 iks_insert_attrib(field_node_type, "var", "pubsub#node_type"); 03808 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type)); 03809 } 03810 field_node_config = iks_insert(x, "field"); 03811 iks_insert_attrib(field_node_config, "var", "FORM_TYPE"); 03812 iks_insert_attrib(field_node_config, "type", "hidden"); 03813 iks_insert_cdata(iks_insert(field_node_config, "value"), 03814 "http://jabber.org/protocol/pubsub#node_config", 45); 03815 field_deliver_payload = iks_insert(x, "field"); 03816 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads"); 03817 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1); 03818 field_persist_items = iks_insert(x, "field"); 03819 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items"); 03820 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1); 03821 field_access_model = iks_insert(x, "field"); 03822 iks_insert_attrib(field_access_model, "var", "pubsub#access_model"); 03823 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9); 03824 if (node_type && !strcasecmp(node_type, "leaf")) { 03825 field_pubsub_collection = iks_insert(x, "field"); 03826 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection"); 03827 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name, 03828 strlen(collection_name)); 03829 } 03830 return configure; 03831 }
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 3523 of file res_jabber.c.
References aji_pubsub_iq_create().
Referenced by aji_pubsub_purge_nodes(), and aji_request_pubsub_nodes().
03524 { 03525 iks *request = aji_pubsub_iq_create(client, "get"); 03526 iks *query; 03527 query = iks_insert(request, "query"); 03528 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 03529 if (collection) { 03530 iks_insert_attrib(query, "node", collection); 03531 } 03532 return request; 03533 }
static iks * aji_build_publish_skeleton | ( | struct aji_client * | client, | |
const char * | node, | |||
const char * | event_type | |||
) | [static] |
Build the skeleton of a publish.
client | the configured XMPP client we use to connect to a XMPP server | |
node | Name of the node that will be published to | |
event_type |
Definition at line 3353 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_test_flag, and globalflags.
Referenced by aji_publish_device_state(), and aji_publish_mwi().
03355 { 03356 iks *request = aji_pubsub_iq_create(client, "set"); 03357 iks *pubsub, *publish, *item; 03358 pubsub = iks_insert(request, "pubsub"); 03359 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03360 publish = iks_insert(pubsub, "publish"); 03361 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03362 iks_insert_attrib(publish, "node", node); 03363 } else { 03364 iks_insert_attrib(publish, "node", event_type); 03365 } 03366 item = iks_insert(publish, "item"); 03367 iks_insert_attrib(item, "id", node); 03368 return item; 03369 03370 }
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 3839 of file res_jabber.c.
References aji_create_pubsub_collection(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ASTOBJ_CONTAINER_FIND, 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.
03840 { 03841 struct aji_client *client; 03842 const char *name; 03843 const char *collection_name; 03844 03845 switch (cmd) { 03846 case CLI_INIT: 03847 e->command = "jabber create collection"; 03848 e->usage = 03849 "Usage: jabber create collection <connection> <collection>\n" 03850 " Creates a PubSub collection node using the account\n" 03851 " as configured in jabber.conf.\n"; 03852 return NULL; 03853 case CLI_GENERATE: 03854 return NULL; 03855 } 03856 03857 if (a->argc != 5) { 03858 return CLI_SHOWUSAGE; 03859 } 03860 name = a->argv[3]; 03861 collection_name = a->argv[4]; 03862 03863 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03864 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03865 return CLI_FAILURE; 03866 } 03867 03868 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03869 aji_create_pubsub_collection(client, collection_name); 03870 return CLI_SUCCESS; 03871 }
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 3877 of file res_jabber.c.
References aji_create_pubsub_leaf(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ASTOBJ_CONTAINER_FIND, 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.
03878 { 03879 struct aji_client *client; 03880 const char *name; 03881 const char *collection_name; 03882 const char *leaf_name; 03883 03884 switch (cmd) { 03885 case CLI_INIT: 03886 e->command = "jabber create leaf"; 03887 e->usage = 03888 "Usage: jabber create leaf <connection> <collection> <leaf>\n" 03889 " Creates a PubSub leaf node using the account\n" 03890 " as configured in jabber.conf.\n"; 03891 return NULL; 03892 case CLI_GENERATE: 03893 return NULL; 03894 } 03895 03896 if (a->argc != 6) { 03897 return CLI_SHOWUSAGE; 03898 } 03899 name = a->argv[3]; 03900 collection_name = a->argv[4]; 03901 leaf_name = a->argv[5]; 03902 03903 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03904 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03905 return CLI_FAILURE; 03906 } 03907 03908 ast_cli(a->fd, "Creating test PubSub node collection.\n"); 03909 aji_create_pubsub_leaf(client, collection_name, leaf_name); 03910 return CLI_SUCCESS; 03911 }
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 3692 of file res_jabber.c.
References aji_delete_pubsub_node(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ASTOBJ_CONTAINER_FIND, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, and ast_cli_entry::usage.
03694 { 03695 struct aji_client *client; 03696 const char *name; 03697 03698 switch (cmd) { 03699 case CLI_INIT: 03700 e->command = "jabber delete node"; 03701 e->usage = 03702 "Usage: jabber delete node <connection> <node>\n" 03703 " Deletes a node on PubSub server\n" 03704 " as configured in jabber.conf.\n"; 03705 return NULL; 03706 case CLI_GENERATE: 03707 return NULL; 03708 } 03709 03710 if (a->argc != 5) { 03711 return CLI_SHOWUSAGE; 03712 } 03713 name = a->argv[3]; 03714 03715 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03716 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03717 return CLI_FAILURE; 03718 } 03719 aji_delete_pubsub_node(client, a->argv[4]); 03720 return CLI_SUCCESS; 03721 }
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 3568 of file res_jabber.c.
References aji_request_pubsub_nodes(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ASTOBJ_CONTAINER_FIND, 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.
03570 { 03571 struct aji_client *client; 03572 const char *name = NULL; 03573 const char *collection = NULL; 03574 03575 switch (cmd) { 03576 case CLI_INIT: 03577 e->command = "jabber list nodes"; 03578 e->usage = 03579 "Usage: jabber list nodes <connection> [collection]\n" 03580 " Lists the user's nodes on the respective connection\n" 03581 " ([connection] as configured in jabber.conf.)\n"; 03582 return NULL; 03583 case CLI_GENERATE: 03584 return NULL; 03585 } 03586 03587 if (a->argc > 5 || a->argc < 4) { 03588 return CLI_SHOWUSAGE; 03589 } else if (a->argc == 4 || a->argc == 5) { 03590 name = a->argv[3]; 03591 } 03592 if (a->argc == 5) { 03593 collection = a->argv[4]; 03594 } 03595 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03596 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03597 return CLI_FAILURE; 03598 } 03599 03600 ast_cli(a->fd, "Listing pubsub nodes.\n"); 03601 aji_request_pubsub_nodes(client, collection); 03602 return CLI_SUCCESS; 03603 }
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 3612 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_cli(), ast_test_flag, ASTOBJ_CONTAINER_FIND, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, clients, ast_cli_entry::command, ast_cli_args::fd, name, pubsubflags, and ast_cli_entry::usage.
03614 { 03615 struct aji_client *client; 03616 const char *name; 03617 03618 switch (cmd) { 03619 case CLI_INIT: 03620 e->command = "jabber purge nodes"; 03621 e->usage = 03622 "Usage: jabber purge nodes <connection> <node>\n" 03623 " Purges nodes on PubSub server\n" 03624 " as configured in jabber.conf.\n"; 03625 return NULL; 03626 case CLI_GENERATE: 03627 return NULL; 03628 } 03629 03630 if (a->argc != 5) { 03631 return CLI_SHOWUSAGE; 03632 } 03633 name = a->argv[3]; 03634 03635 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 03636 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 03637 return CLI_FAILURE; 03638 } 03639 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03640 aji_pubsub_purge_nodes(client, a->argv[4]); 03641 } else { 03642 aji_delete_pubsub_node(client, a->argv[4]); 03643 } 03644 return CLI_SUCCESS; 03645 }
static int aji_client_connect | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3063 of file res_jabber.c.
References aji_client_destroy(), AJI_CONNECTING, AJI_DISCONNECTED, aji_filter_roster(), aji_get_roster(), aji_init_event_distribution(), 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().
03064 { 03065 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03066 int res = IKS_FILTER_PASS; 03067 03068 if (client) { 03069 if (client->state == AJI_DISCONNECTED) { 03070 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); 03071 client->state = AJI_CONNECTING; 03072 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid; 03073 if (!client->component) { /*client*/ 03074 aji_get_roster(client); 03075 } 03076 if (client->distribute_events) { 03077 aji_init_event_distribution(client); 03078 } 03079 03080 iks_filter_remove_hook(client->f, aji_client_connect); 03081 /* Once we remove the hook for this routine, we must return EAT or we will crash or corrupt memory */ 03082 res = IKS_FILTER_EAT; 03083 } 03084 } else { 03085 ast_log(LOG_ERROR, "Out of memory.\n"); 03086 } 03087 03088 ASTOBJ_UNREF(client, aji_client_destroy); 03089 return res; 03090 }
static void aji_client_destroy | ( | struct aji_client * | obj | ) | [static] |
Definition at line 413 of file res_jabber.c.
References aji_buddy_destroy(), aji_message_destroy(), ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, aji_client::buddies, aji_client::f, aji_message::list, aji_client::messages, aji_client::p, and aji_client::stack.
Referenced by acf_jabberreceive_read(), aji_act_hook(), aji_client_connect(), aji_client_info_handler(), aji_create_client(), aji_dinfo_handler(), aji_ditems_handler(), aji_join_exec(), aji_leave_exec(), aji_log_hook(), aji_recv_loop(), aji_register_approve_handler(), aji_register_query_handler(), aji_reload(), aji_sendgroup_exec(), ast_aji_disconnect(), and unload_module().
00414 { 00415 struct aji_message *tmp; 00416 ASTOBJ_CONTAINER_DESTROYALL(&obj->buddies, aji_buddy_destroy); 00417 ASTOBJ_CONTAINER_DESTROY(&obj->buddies); 00418 iks_filter_delete(obj->f); 00419 iks_parser_delete(obj->p); 00420 iks_stack_delete(obj->stack); 00421 AST_LIST_LOCK(&obj->messages); 00422 while ((tmp = AST_LIST_REMOVE_HEAD(&obj->messages, list))) { 00423 aji_message_destroy(tmp); 00424 } 00425 AST_LIST_HEAD_DESTROY(&obj->messages); 00426 ast_free(obj); 00427 }
static int aji_client_info_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2000 of file res_jabber.c.
References aji_client_destroy(), aji_find_resource(), ast_aji_send(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_REF, ASTOBJ_UNREF, aji_client::buddies, aji_resource::cap, aji_client::jid, aji_version::jingle, LOG_ERROR, LOG_NOTICE, and aji_resource::resource.
Referenced by aji_create_client().
02001 { 02002 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02003 struct aji_resource *resource = NULL; 02004 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02005 02006 resource = aji_find_resource(buddy, pak->from->resource); 02007 if (pak->subtype == IKS_TYPE_RESULT) { 02008 if (!resource) { 02009 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02010 ASTOBJ_UNREF(client, aji_client_destroy); 02011 return IKS_FILTER_EAT; 02012 } 02013 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02014 resource->cap->jingle = 1; 02015 } else { 02016 resource->cap->jingle = 0; 02017 } 02018 } else if (pak->subtype == IKS_TYPE_GET) { 02019 iks *iq, *disco, *ident, *google, *query; 02020 iq = iks_new("iq"); 02021 query = iks_new("query"); 02022 ident = iks_new("identity"); 02023 disco = iks_new("feature"); 02024 google = iks_new("feature"); 02025 if (iq && ident && disco && google) { 02026 iks_insert_attrib(iq, "from", client->jid->full); 02027 iks_insert_attrib(iq, "to", pak->from->full); 02028 iks_insert_attrib(iq, "type", "result"); 02029 iks_insert_attrib(iq, "id", pak->id); 02030 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02031 iks_insert_attrib(ident, "category", "client"); 02032 iks_insert_attrib(ident, "type", "pc"); 02033 iks_insert_attrib(ident, "name", "asterisk"); 02034 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info"); 02035 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1"); 02036 iks_insert_node(iq, query); 02037 iks_insert_node(query, ident); 02038 iks_insert_node(query, google); 02039 iks_insert_node(query, disco); 02040 ast_aji_send(client, iq); 02041 } else { 02042 ast_log(LOG_ERROR, "Out of Memory.\n"); 02043 } 02044 02045 iks_delete(iq); 02046 iks_delete(query); 02047 iks_delete(ident); 02048 iks_delete(google); 02049 iks_delete(disco); 02050 } else if (pak->subtype == IKS_TYPE_ERROR) { 02051 ast_log(LOG_NOTICE, "User %s does not support discovery.\n", pak->from->full); 02052 } 02053 ASTOBJ_UNREF(client, aji_client_destroy); 02054 return IKS_FILTER_EAT; 02055 }
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 3288 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().
03289 { 03290 int res = 0; 03291 iks *modify_affiliates = aji_pubsub_iq_create(client, "set"); 03292 iks *pubsub, *affiliations, *affiliate; 03293 pubsub = iks_insert(modify_affiliates, "pubsub"); 03294 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03295 affiliations = iks_insert(pubsub, "affiliations"); 03296 iks_insert_attrib(affiliations, "node", node); 03297 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 03298 ASTOBJ_RDLOCK(iterator); 03299 affiliate = iks_insert(affiliations, "affiliation"); 03300 iks_insert_attrib(affiliate, "jid", iterator->name); 03301 iks_insert_attrib(affiliate, "affiliation", "owner"); 03302 ASTOBJ_UNLOCK(iterator); 03303 }); 03304 res = ast_aji_send(client, modify_affiliates); 03305 iks_delete(modify_affiliates); 03306 }
static int aji_create_buddy | ( | char * | label, | |
struct aji_client * | client | |||
) | [static] |
load config file.
Definition at line 4478 of file res_jabber.c.
References aji_buddy_destroy(), ast_calloc, ast_copy_string(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_LINK, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, LOG_WARNING, and aji_buddy::name.
Referenced by aji_create_client(), aji_handle_presence(), and aji_handle_subscribe().
static int aji_create_client | ( | char * | label, | |
struct ast_variable * | var, | |||
int | debug | |||
) | [static] |
Definition at line 4233 of file res_jabber.c.
References aji_act_hook(), AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, aji_client_destroy(), aji_client_info_handler(), aji_create_buddy(), aji_dinfo_handler(), AJI_DISCONNECTED, aji_ditems_handler(), aji_log_hook(), AJI_PUBSUB, aji_register_approve_handler(), aji_register_query_handler(), asprintf, ast_calloc, ast_clear_flag, ast_copy_flags, ast_copy_string(), ast_false(), AST_FLAGS_ALL, ast_free, AST_LIST_HEAD_INIT, ast_log(), ast_set2_flag, ast_set_flag, ast_test_flag, ast_true(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_INIT, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_INIT, ASTOBJ_UNLOCK, ASTOBJ_UNMARK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::authorized, aji_client::buddies, clients, aji_client::component, aji_client::debug, aji_client::distribute_events, aji_client::f, aji_client::flags, aji_client::forcessl, globalflags, aji_client::jid, aji_client::keepalive, LOG_ERROR, LOG_WARNING, aji_client::message_timeout, aji_client::messages, aji_client::mid, aji_client::name, aji_client::name_space, aji_client::p, aji_client::password, aji_client::port, aji_client::priority, aji_client::pubsub_node, pubsubflags, aji_client::serverhost, aji_client::stack, aji_client::state, aji_client::status, aji_client::statusmessage, aji_client::timeout, aji_client::user, aji_client::usesasl, aji_client::usetls, and var.
04234 { 04235 char *resource; 04236 struct aji_client *client = NULL; 04237 int flag = 0; 04238 04239 client = ASTOBJ_CONTAINER_FIND(&clients, label); 04240 if (!client) { 04241 flag = 1; 04242 client = ast_calloc(1, sizeof(*client)); 04243 if (!client) { 04244 ast_log(LOG_ERROR, "Out of memory!\n"); 04245 return 0; 04246 } 04247 ASTOBJ_INIT(client); 04248 ASTOBJ_WRLOCK(client); 04249 ASTOBJ_CONTAINER_INIT(&client->buddies); 04250 } else { 04251 ASTOBJ_WRLOCK(client); 04252 ASTOBJ_UNMARK(client); 04253 } 04254 ASTOBJ_CONTAINER_MARKALL(&client->buddies); 04255 ast_copy_string(client->name, label, sizeof(client->name)); 04256 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid)); 04257 04258 /* Set default values for the client object */ 04259 client->debug = debug; 04260 ast_copy_flags(&client->flags, &globalflags, AST_FLAGS_ALL); 04261 client->port = 5222; 04262 client->usetls = 1; 04263 client->usesasl = 1; 04264 client->forcessl = 0; 04265 client->keepalive = 1; 04266 client->timeout = 50; 04267 client->message_timeout = 5; 04268 client->distribute_events = 0; 04269 AST_LIST_HEAD_INIT(&client->messages); 04270 client->component = 0; 04271 ast_copy_string(client->statusmessage, "Online and Available", sizeof(client->statusmessage)); 04272 client->priority = 0; 04273 client->status = IKS_SHOW_AVAILABLE; 04274 04275 if (flag) { 04276 client->authorized = 0; 04277 client->state = AJI_DISCONNECTED; 04278 } 04279 while (var) { 04280 if (!strcasecmp(var->name, "username")) { 04281 ast_copy_string(client->user, var->value, sizeof(client->user)); 04282 } else if (!strcasecmp(var->name, "serverhost")) { 04283 ast_copy_string(client->serverhost, var->value, sizeof(client->serverhost)); 04284 } else if (!strcasecmp(var->name, "secret")) { 04285 ast_copy_string(client->password, var->value, sizeof(client->password)); 04286 } else if (!strcasecmp(var->name, "statusmessage")) { 04287 ast_copy_string(client->statusmessage, var->value, sizeof(client->statusmessage)); 04288 } else if (!strcasecmp(var->name, "port")) { 04289 client->port = atoi(var->value); 04290 } else if (!strcasecmp(var->name, "timeout")) { 04291 client->message_timeout = atoi(var->value); 04292 } else if (!strcasecmp(var->name, "debug")) { 04293 client->debug = (ast_false(var->value)) ? 0 : 1; 04294 } else if (!strcasecmp(var->name, "type")) { 04295 if (!strcasecmp(var->value, "component")) { 04296 client->component = 1; 04297 if (client->distribute_events) { 04298 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04299 client->distribute_events = 0; 04300 } 04301 } 04302 } else if (!strcasecmp(var->name, "distribute_events")) { 04303 if (ast_true(var->value)) { 04304 if (client->component) { 04305 ast_log(LOG_ERROR, "Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n"); 04306 } else { 04307 if (ast_test_flag(&pubsubflags, AJI_PUBSUB)) { 04308 ast_log(LOG_ERROR, "Only one connection can be configured for distributed events.\n"); 04309 } else { 04310 ast_set_flag(&pubsubflags, AJI_PUBSUB); 04311 client->distribute_events = 1; 04312 } 04313 } 04314 } 04315 } else if (!strcasecmp(var->name, "pubsub_node")) { 04316 ast_copy_string(client->pubsub_node, var->value, sizeof(client->pubsub_node)); 04317 } else if (!strcasecmp(var->name, "usetls")) { 04318 client->usetls = (ast_false(var->value)) ? 0 : 1; 04319 } else if (!strcasecmp(var->name, "usesasl")) { 04320 client->usesasl = (ast_false(var->value)) ? 0 : 1; 04321 } else if (!strcasecmp(var->name, "forceoldssl")) { 04322 client->forcessl = (ast_false(var->value)) ? 0 : 1; 04323 } else if (!strcasecmp(var->name, "keepalive")) { 04324 client->keepalive = (ast_false(var->value)) ? 0 : 1; 04325 } else if (!strcasecmp(var->name, "autoprune")) { 04326 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOPRUNE); 04327 } else if (!strcasecmp(var->name, "autoregister")) { 04328 ast_set2_flag(&client->flags, ast_true(var->value), AJI_AUTOREGISTER); 04329 } else if (!strcasecmp(var->name, "auth_policy")) { 04330 if (!strcasecmp(var->value, "accept")) { 04331 ast_set_flag(&client->flags, AJI_AUTOACCEPT); 04332 } else { 04333 ast_clear_flag(&client->flags, AJI_AUTOACCEPT); 04334 } 04335 } else if (!strcasecmp(var->name, "buddy")) { 04336 aji_create_buddy((char *)var->value, client); 04337 } else if (!strcasecmp(var->name, "priority")) { 04338 client->priority = atoi(var->value); 04339 } else if (!strcasecmp(var->name, "status")) { 04340 if (!strcasecmp(var->value, "unavailable")) { 04341 client->status = IKS_SHOW_UNAVAILABLE; 04342 } else if (!strcasecmp(var->value, "available") 04343 || !strcasecmp(var->value, "online")) { 04344 client->status = IKS_SHOW_AVAILABLE; 04345 } else if (!strcasecmp(var->value, "chat") 04346 || !strcasecmp(var->value, "chatty")) { 04347 client->status = IKS_SHOW_CHAT; 04348 } else if (!strcasecmp(var->value, "away")) { 04349 client->status = IKS_SHOW_AWAY; 04350 } else if (!strcasecmp(var->value, "xa") 04351 || !strcasecmp(var->value, "xaway")) { 04352 client->status = IKS_SHOW_XA; 04353 } else if (!strcasecmp(var->value, "dnd")) { 04354 client->status = IKS_SHOW_DND; 04355 } else if (!strcasecmp(var->value, "invisible")) { 04356 #ifdef IKS_SHOW_INVISIBLE 04357 client->status = IKS_SHOW_INVISIBLE; 04358 #else 04359 ast_log(LOG_WARNING, "Your iksemel doesn't support invisible status: falling back to DND\n"); 04360 client->status = IKS_SHOW_DND; 04361 #endif 04362 } else { 04363 ast_log(LOG_WARNING, "Unknown presence status: %s\n", var->value); 04364 } 04365 } 04366 /* no transport support in this version */ 04367 /* else if (!strcasecmp(var->name, "transport")) 04368 aji_create_transport(var->value, client); 04369 */ 04370 var = var->next; 04371 } 04372 if (!flag) { 04373 ASTOBJ_UNLOCK(client); 04374 ASTOBJ_UNREF(client, aji_client_destroy); 04375 return 1; 04376 } 04377 04378 ast_copy_string(client->name_space, (client->component) ? "jabber:component:accept" : "jabber:client", sizeof(client->name_space)); 04379 client->p = iks_stream_new(client->name_space, client, aji_act_hook); 04380 if (!client->p) { 04381 ast_log(LOG_ERROR, "Failed to create stream for client '%s'!\n", client->name); 04382 return 0; 04383 } 04384 client->stack = iks_stack_new(8192, 8192); 04385 if (!client->stack) { 04386 ast_log(LOG_ERROR, "Failed to allocate stack for client '%s'\n", client->name); 04387 return 0; 04388 } 04389 client->f = iks_filter_new(); 04390 if (!client->f) { 04391 ast_log(LOG_ERROR, "Failed to create filter for client '%s'\n", client->name); 04392 return 0; 04393 } 04394 if (!strchr(client->user, '/') && !client->component) { /*client */ 04395 resource = NULL; 04396 if (asprintf(&resource, "%s/asterisk", client->user) >= 0) { 04397 client->jid = iks_id_new(client->stack, resource); 04398 ast_free(resource); 04399 } 04400 } else { 04401 client->jid = iks_id_new(client->stack, client->user); 04402 } 04403 if (client->component) { 04404 iks_filter_add_rule(client->f, aji_dinfo_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04405 iks_filter_add_rule(client->f, aji_ditems_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE); 04406 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); 04407 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); 04408 } else { 04409 iks_filter_add_rule(client->f, aji_client_info_handler, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE); 04410 } 04411 04412 iks_set_log_hook(client->p, aji_log_hook); 04413 ASTOBJ_UNLOCK(client); 04414 ASTOBJ_CONTAINER_LINK(&clients, client); 04415 return 1; 04416 }
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 3746 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_collection(), and aji_handle_pubsub_error().
03748 { 03749 aji_create_pubsub_node(client, "collection", collection_name, NULL); 03750 }
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 3759 of file res_jabber.c.
References aji_create_pubsub_node().
Referenced by aji_cli_create_leafnode(), and aji_handle_pubsub_error().
03761 { 03762 aji_create_pubsub_node(client, "leaf", leaf_name, collection_name); 03763 }
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 3772 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().
03774 { 03775 int res = 0; 03776 iks *node = aji_pubsub_iq_create(client, "set"); 03777 iks *pubsub, *create, *configure; 03778 pubsub = iks_insert(node, "pubsub"); 03779 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03780 create = iks_insert(pubsub, "create"); 03781 iks_insert_attrib(create, "node", name); 03782 configure = aji_build_node_config(pubsub, node_type, collection_name); 03783 res = ast_aji_send(client, node); 03784 aji_create_affiliations(client, name); 03785 iks_delete(node); 03786 return 0; 03787 }
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 3665 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().
03666 { 03667 03668 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03669 iks *item = NULL; 03670 if (iks_has_children(pak->query)) { 03671 item = iks_first_tag(pak->query); 03672 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial, 03673 iks_find_attrib(item, "node")); 03674 while ((item = iks_next_tag(item))) { 03675 aji_delete_pubsub_node(client, iks_find_attrib(item, "node")); 03676 } 03677 } 03678 if (item) { 03679 iks_delete(item); 03680 } 03681 return IKS_FILTER_EAT; 03682 }
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 3729 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().
03730 { 03731 iks *request = aji_pubsub_iq_create(client, "set"); 03732 iks *pubsub, *delete; 03733 pubsub = iks_insert(request, "pubsub"); 03734 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner"); 03735 delete = iks_insert(pubsub, "delete"); 03736 iks_insert_attrib(delete, "node", node_name); 03737 ast_aji_send(client, request); 03738 }
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 3181 of file res_jabber.c.
References aji_publish_device_state(), ast_devstate_str(), ast_eid_cmp(), ast_eid_default, ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ast_log(), ASTOBJ_REF, and LOG_DEBUG.
Referenced by aji_init_event_distribution().
03182 { 03183 const char *device; 03184 const char *device_state; 03185 struct aji_client *client; 03186 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03187 { 03188 /* If the event didn't originate from this server, don't send it back out. */ 03189 ast_log(LOG_DEBUG, "Returning here\n"); 03190 return; 03191 } 03192 03193 client = ASTOBJ_REF((struct aji_client *) data); 03194 device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); 03195 device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); 03196 aji_publish_device_state(client, device, device_state); 03197 }
static int aji_dinfo_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2064 of file res_jabber.c.
References aji_client_destroy(), aji_find_resource(), 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().
02065 { 02066 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02067 char *node = NULL; 02068 struct aji_resource *resource = NULL; 02069 struct aji_buddy *buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02070 02071 resource = aji_find_resource(buddy, pak->from->resource); 02072 if (pak->subtype == IKS_TYPE_ERROR) { 02073 ast_log(LOG_WARNING, "Received error from a client, turn on jabber debug!\n"); 02074 return IKS_FILTER_EAT; 02075 } 02076 if (pak->subtype == IKS_TYPE_RESULT) { 02077 if (!resource) { 02078 ast_log(LOG_NOTICE, "JABBER: Received client info from %s when not requested.\n", pak->from->full); 02079 ASTOBJ_UNREF(client, aji_client_destroy); 02080 return IKS_FILTER_EAT; 02081 } 02082 if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) { 02083 resource->cap->jingle = 1; 02084 } else { 02085 resource->cap->jingle = 0; 02086 } 02087 } else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query, "node"))) { 02088 iks *iq, *query, *identity, *disco, *reg, *commands, *gateway, *version, *vcard, *search; 02089 02090 iq = iks_new("iq"); 02091 query = iks_new("query"); 02092 identity = iks_new("identity"); 02093 disco = iks_new("feature"); 02094 reg = iks_new("feature"); 02095 commands = iks_new("feature"); 02096 gateway = iks_new("feature"); 02097 version = iks_new("feature"); 02098 vcard = iks_new("feature"); 02099 search = iks_new("feature"); 02100 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) { 02101 iks_insert_attrib(iq, "from", client->user); 02102 iks_insert_attrib(iq, "to", pak->from->full); 02103 iks_insert_attrib(iq, "id", pak->id); 02104 iks_insert_attrib(iq, "type", "result"); 02105 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02106 iks_insert_attrib(identity, "category", "gateway"); 02107 iks_insert_attrib(identity, "type", "pstn"); 02108 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX"); 02109 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco"); 02110 iks_insert_attrib(reg, "var", "jabber:iq:register"); 02111 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands"); 02112 iks_insert_attrib(gateway, "var", "jabber:iq:gateway"); 02113 iks_insert_attrib(version, "var", "jabber:iq:version"); 02114 iks_insert_attrib(vcard, "var", "vcard-temp"); 02115 iks_insert_attrib(search, "var", "jabber:iq:search"); 02116 02117 iks_insert_node(iq, query); 02118 iks_insert_node(query, identity); 02119 iks_insert_node(query, disco); 02120 iks_insert_node(query, reg); 02121 iks_insert_node(query, commands); 02122 iks_insert_node(query, gateway); 02123 iks_insert_node(query, version); 02124 iks_insert_node(query, vcard); 02125 iks_insert_node(query, search); 02126 ast_aji_send(client, iq); 02127 } else { 02128 ast_log(LOG_ERROR, "Out of memory.\n"); 02129 } 02130 02131 iks_delete(iq); 02132 iks_delete(query); 02133 iks_delete(identity); 02134 iks_delete(disco); 02135 iks_delete(reg); 02136 iks_delete(commands); 02137 iks_delete(gateway); 02138 iks_delete(version); 02139 iks_delete(vcard); 02140 iks_delete(search); 02141 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "http://jabber.org/protocol/commands")) { 02142 iks *iq, *query, *confirm; 02143 iq = iks_new("iq"); 02144 query = iks_new("query"); 02145 confirm = iks_new("item"); 02146 02147 if (iq && query && confirm && client) { 02148 iks_insert_attrib(iq, "from", client->user); 02149 iks_insert_attrib(iq, "to", pak->from->full); 02150 iks_insert_attrib(iq, "id", pak->id); 02151 iks_insert_attrib(iq, "type", "result"); 02152 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 02153 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 02154 iks_insert_attrib(confirm, "node", "confirmaccount"); 02155 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 02156 iks_insert_attrib(confirm, "jid", client->user); 02157 iks_insert_node(iq, query); 02158 iks_insert_node(query, confirm); 02159 ast_aji_send(client, iq); 02160 } else { 02161 ast_log(LOG_ERROR, "Out of memory.\n"); 02162 } 02163 02164 iks_delete(iq); 02165 iks_delete(query); 02166 iks_delete(confirm); 02167 02168 } else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node, "confirmaccount")) { 02169 iks *iq, *query, *feature; 02170 02171 iq = iks_new("iq"); 02172 query = iks_new("query"); 02173 feature = iks_new("feature"); 02174 02175 if (iq && query && feature && client) { 02176 iks_insert_attrib(iq, "from", client->user); 02177 iks_insert_attrib(iq, "to", pak->from->full); 02178 iks_insert_attrib(iq, "id", pak->id); 02179 iks_insert_attrib(iq, "type", "result"); 02180 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02181 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 02182 iks_insert_node(iq, query); 02183 iks_insert_node(query, feature); 02184 ast_aji_send(client, iq); 02185 } else { 02186 ast_log(LOG_ERROR, "Out of memory.\n"); 02187 } 02188 02189 iks_delete(iq); 02190 iks_delete(query); 02191 iks_delete(feature); 02192 } 02193 02194 ASTOBJ_UNREF(client, aji_client_destroy); 02195 return IKS_FILTER_EAT; 02196 }
static int aji_ditems_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1903 of file res_jabber.c.
References aji_client_destroy(), ast_aji_send(), ast_log(), ASTOBJ_REF, ASTOBJ_UNREF, LOG_ERROR, and aji_client::user.
Referenced by aji_create_client().
01904 { 01905 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01906 char *node = NULL; 01907 01908 if (!(node = iks_find_attrib(pak->query, "node"))) { 01909 iks *iq = NULL, *query = NULL, *item = NULL; 01910 iq = iks_new("iq"); 01911 query = iks_new("query"); 01912 item = iks_new("item"); 01913 01914 if (iq && query && item) { 01915 iks_insert_attrib(iq, "from", client->user); 01916 iks_insert_attrib(iq, "to", pak->from->full); 01917 iks_insert_attrib(iq, "id", pak->id); 01918 iks_insert_attrib(iq, "type", "result"); 01919 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01920 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands"); 01921 iks_insert_attrib(item, "name", "Million Dollar Asterisk Commands"); 01922 iks_insert_attrib(item, "jid", client->user); 01923 01924 iks_insert_node(iq, query); 01925 iks_insert_node(query, item); 01926 ast_aji_send(client, iq); 01927 } else { 01928 ast_log(LOG_ERROR, "Out of memory.\n"); 01929 } 01930 01931 iks_delete(iq); 01932 iks_delete(query); 01933 iks_delete(item); 01934 01935 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) { 01936 iks *iq, *query, *confirm; 01937 iq = iks_new("iq"); 01938 query = iks_new("query"); 01939 confirm = iks_new("item"); 01940 if (iq && query && confirm && client) { 01941 iks_insert_attrib(iq, "from", client->user); 01942 iks_insert_attrib(iq, "to", pak->from->full); 01943 iks_insert_attrib(iq, "id", pak->id); 01944 iks_insert_attrib(iq, "type", "result"); 01945 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01946 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands"); 01947 iks_insert_attrib(confirm, "node", "confirmaccount"); 01948 iks_insert_attrib(confirm, "name", "Confirm AIM account"); 01949 iks_insert_attrib(confirm, "jid", "blog.astjab.org"); 01950 01951 iks_insert_node(iq, query); 01952 iks_insert_node(query, confirm); 01953 ast_aji_send(client, iq); 01954 } else { 01955 ast_log(LOG_ERROR, "Out of memory.\n"); 01956 } 01957 01958 iks_delete(iq); 01959 iks_delete(query); 01960 iks_delete(confirm); 01961 01962 } else if (!strcasecmp(node, "confirmaccount")) { 01963 iks *iq = NULL, *query = NULL, *feature = NULL; 01964 01965 iq = iks_new("iq"); 01966 query = iks_new("query"); 01967 feature = iks_new("feature"); 01968 01969 if (iq && query && feature && client) { 01970 iks_insert_attrib(iq, "from", client->user); 01971 iks_insert_attrib(iq, "to", pak->from->full); 01972 iks_insert_attrib(iq, "id", pak->id); 01973 iks_insert_attrib(iq, "type", "result"); 01974 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items"); 01975 iks_insert_attrib(feature, "var", "http://jabber.org/protocol/commands"); 01976 iks_insert_node(iq, query); 01977 iks_insert_node(query, feature); 01978 ast_aji_send(client, iq); 01979 } else { 01980 ast_log(LOG_ERROR, "Out of memory.\n"); 01981 } 01982 01983 iks_delete(iq); 01984 iks_delete(query); 01985 iks_delete(feature); 01986 } 01987 01988 ASTOBJ_UNREF(client, aji_client_destroy); 01989 return IKS_FILTER_EAT; 01990 01991 }
static char * aji_do_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4051 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.
04052 { 04053 switch (cmd) { 04054 case CLI_INIT: 04055 e->command = "jabber reload"; 04056 e->usage = 04057 "Usage: jabber reload\n" 04058 " Reloads the Jabber module.\n"; 04059 return NULL; 04060 case CLI_GENERATE: 04061 return NULL; 04062 } 04063 04064 aji_reload(1); 04065 ast_cli(a->fd, "Jabber Reloaded.\n"); 04066 return CLI_SUCCESS; 04067 }
static char * aji_do_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4009 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.
04010 { 04011 switch (cmd) { 04012 case CLI_INIT: 04013 e->command = "jabber set debug {on|off}"; 04014 e->usage = 04015 "Usage: jabber set debug {on|off}\n" 04016 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n"; 04017 return NULL; 04018 case CLI_GENERATE: 04019 return NULL; 04020 } 04021 04022 if (a->argc != e->args) { 04023 return CLI_SHOWUSAGE; 04024 } 04025 04026 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 04027 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04028 ASTOBJ_RDLOCK(iterator); 04029 iterator->debug = 1; 04030 ASTOBJ_UNLOCK(iterator); 04031 }); 04032 ast_cli(a->fd, "Jabber Debugging Enabled.\n"); 04033 return CLI_SUCCESS; 04034 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 04035 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04036 ASTOBJ_RDLOCK(iterator); 04037 iterator->debug = 0; 04038 ASTOBJ_UNLOCK(iterator); 04039 }); 04040 ast_cli(a->fd, "Jabber Debugging Disabled.\n"); 04041 return CLI_SUCCESS; 04042 } 04043 return CLI_SHOWUSAGE; /* defaults to invalid */ 04044 }
static int aji_filter_roster | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2929 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().
02930 { 02931 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02932 int flag = 0; 02933 iks *x = NULL; 02934 struct aji_buddy *buddy; 02935 02936 client->state = AJI_CONNECTED; 02937 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02938 ASTOBJ_RDLOCK(iterator); 02939 x = iks_child(pak->query); 02940 flag = 0; 02941 while (x) { 02942 if (!iks_strcmp(iks_name(x), "item")) { 02943 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) { 02944 flag = 1; 02945 ast_clear_flag(&iterator->flags, AJI_AUTOPRUNE | AJI_AUTOREGISTER); 02946 } 02947 } 02948 x = iks_next(x); 02949 } 02950 if (!flag) { 02951 ast_copy_flags(&iterator->flags, &client->flags, AJI_AUTOREGISTER); 02952 } 02953 iks_delete(x); 02954 02955 ASTOBJ_UNLOCK(iterator); 02956 }); 02957 02958 x = iks_child(pak->query); 02959 while (x) { 02960 flag = 0; 02961 if (iks_strcmp(iks_name(x), "item") == 0) { 02962 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02963 ASTOBJ_RDLOCK(iterator); 02964 if (!strcasecmp(iterator->name, iks_find_attrib(x, "jid"))) 02965 flag = 1; 02966 ASTOBJ_UNLOCK(iterator); 02967 }); 02968 02969 if (flag) { 02970 /* found buddy, don't create a new one */ 02971 x = iks_next(x); 02972 continue; 02973 } 02974 02975 buddy = ast_calloc(1, sizeof(*buddy)); 02976 if (!buddy) { 02977 ast_log(LOG_WARNING, "Out of memory\n"); 02978 return 0; 02979 } 02980 ASTOBJ_INIT(buddy); 02981 ASTOBJ_WRLOCK(buddy); 02982 ast_copy_string(buddy->name, iks_find_attrib(x, "jid"), sizeof(buddy->name)); 02983 ast_clear_flag(&buddy->flags, AST_FLAGS_ALL); 02984 if (ast_test_flag(&client->flags, AJI_AUTOPRUNE)) { 02985 ast_set_flag(&buddy->flags, AJI_AUTOPRUNE); 02986 ASTOBJ_MARK(buddy); 02987 } else if (!iks_strcmp(iks_find_attrib(x, "subscription"), "none") || !iks_strcmp(iks_find_attrib(x, "subscription"), "from")) { 02988 /* subscribe to buddy's presence only 02989 if we really need to */ 02990 ast_set_flag(&buddy->flags, AJI_AUTOREGISTER); 02991 } 02992 ASTOBJ_UNLOCK(buddy); 02993 if (buddy) { 02994 ASTOBJ_CONTAINER_LINK(&client->buddies, buddy); 02995 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02996 } 02997 } 02998 x = iks_next(x); 02999 } 03000 03001 iks_delete(x); 03002 aji_pruneregister(client); 03003 03004 ASTOBJ_UNREF(client, aji_client_destroy); 03005 return IKS_FILTER_EAT; 03006 }
static struct aji_resource* aji_find_resource | ( | struct aji_buddy * | buddy, | |
char * | name | |||
) | [static] |
Definition at line 547 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().
00548 { 00549 struct aji_resource *res = NULL; 00550 if (!buddy || !name) { 00551 return res; 00552 } 00553 res = buddy->resources; 00554 while (res) { 00555 if (!strcasecmp(res->resource, name)) { 00556 break; 00557 } 00558 res = res->next; 00559 } 00560 return res; 00561 }
static struct aji_version* aji_find_version | ( | char * | node, | |
char * | version, | |||
ikspak * | pak | |||
) | [static] |
Definition at line 475 of file res_jabber.c.
References ast_copy_string(), ast_free, ast_log(), ast_malloc, capabilities, LOG_ERROR, aji_capabilities::next, aji_version::next, aji_capabilities::node, aji_version::version, and aji_capabilities::versions.
Referenced by aji_handle_presence().
00476 { 00477 struct aji_capabilities *list = NULL; 00478 struct aji_version *res = NULL; 00479 00480 list = capabilities; 00481 00482 if (!node) { 00483 node = pak->from->full; 00484 } 00485 if (!version) { 00486 version = "none supplied."; 00487 } 00488 while (list) { 00489 if (!strcasecmp(list->node, node)) { 00490 res = list->versions; 00491 while(res) { 00492 if (!strcasecmp(res->version, version)) { 00493 return res; 00494 } 00495 res = res->next; 00496 } 00497 /* Specified version not found. Let's add it to 00498 this node in our capabilities list */ 00499 if (!res) { 00500 res = ast_malloc(sizeof(*res)); 00501 if (!res) { 00502 ast_log(LOG_ERROR, "Out of memory!\n"); 00503 return NULL; 00504 } 00505 res->jingle = 0; 00506 res->parent = list; 00507 ast_copy_string(res->version, version, sizeof(res->version)); 00508 res->next = list->versions; 00509 list->versions = res; 00510 return res; 00511 } 00512 } 00513 list = list->next; 00514 } 00515 /* Specified node not found. Let's add it our capabilities list */ 00516 if (!list) { 00517 list = ast_malloc(sizeof(*list)); 00518 if (!list) { 00519 ast_log(LOG_ERROR, "Out of memory!\n"); 00520 return NULL; 00521 } 00522 res = ast_malloc(sizeof(*res)); 00523 if (!res) { 00524 ast_log(LOG_ERROR, "Out of memory!\n"); 00525 ast_free(list); 00526 return NULL; 00527 } 00528 ast_copy_string(list->node, node, sizeof(list->node)); 00529 ast_copy_string(res->version, version, sizeof(res->version)); 00530 res->jingle = 0; 00531 res->parent = list; 00532 res->next = NULL; 00533 list->versions = res; 00534 list->next = capabilities; 00535 capabilities = list; 00536 } 00537 return res; 00538 }
static int aji_get_roster | ( | struct aji_client * | client | ) | [static] |
Definition at line 3040 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().
03041 { 03042 iks *roster = NULL; 03043 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER); 03044 03045 if (roster) { 03046 iks_insert_attrib(roster, "id", "roster"); 03047 aji_set_presence(client, NULL, client->jid->full, client->status, client->statusmessage); 03048 ast_aji_send(client, roster); 03049 } 03050 03051 iks_delete(roster); 03052 03053 return 1; 03054 }
static void aji_handle_iq | ( | struct aji_client * | client, | |
iks * | node | |||
) | [static] |
static void aji_handle_message | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2217 of file res_jabber.c.
References ast_calloc, ast_cond_broadcast, ast_copy_string(), ast_debug, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvnow(), delete_old_messages(), aji_message::list, LOG_ERROR, messagelock, aji_client::messages, and aji_client::name.
Referenced by aji_act_hook().
02218 { 02219 struct aji_message *insert; 02220 int deleted = 0; 02221 02222 ast_debug(3, "client %s received a message\n", client->name); 02223 02224 if (!(insert = ast_calloc(1, sizeof(*insert)))) { 02225 return; 02226 } 02227 02228 insert->arrived = ast_tvnow(); 02229 02230 /* wake up threads waiting for messages */ 02231 ast_mutex_lock(&messagelock); 02232 ast_cond_broadcast(&message_received_condition); 02233 ast_mutex_unlock(&messagelock); 02234 02235 if (iks_find_cdata(pak->x, "body")) { 02236 insert->message = ast_strdup(iks_find_cdata(pak->x, "body")); 02237 } 02238 if (pak->id) { 02239 ast_copy_string(insert->id, pak->id, sizeof(insert->id)); 02240 } 02241 if (pak->from){ 02242 /* insert will furtherly be added to message list */ 02243 insert->from = ast_strdup(pak->from->full); 02244 if (!insert->from) { 02245 ast_log(LOG_ERROR, "Memory allocation failure\n"); 02246 return; 02247 } 02248 ast_debug(3, "message comes from %s\n", insert->from); 02249 } 02250 02251 /* remove old messages received from this JID 02252 * and insert received message */ 02253 deleted = delete_old_messages(client, pak->from->partial); 02254 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial); 02255 AST_LIST_LOCK(&client->messages); 02256 AST_LIST_INSERT_HEAD(&client->messages, insert, list); 02257 AST_LIST_UNLOCK(&client->messages); 02258 }
static void aji_handle_presence | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2266 of file res_jabber.c.
References aji_buddy_destroy(), AJI_CONNECTED, aji_create_buddy(), aji_find_version(), aji_set_presence(), ast_aji_increment_mid(), ast_aji_send(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_log(), ast_strdup, ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_UNLOCK, ASTOBJ_UNREF, ASTOBJ_WRLOCK, aji_client::buddies, aji_client::component, descrip, aji_resource::description, EVENT_FLAG_USER, gtalk_yuck(), aji_client::jid, last, LOG_ERROR, LOG_NOTICE, manager_event, aji_client::mid, aji_client::name, aji_resource::next, aji_resource::priority, aji_resource::resource, aji_buddy::resources, aji_client::state, aji_resource::status, aji_client::status, status, and type.
Referenced by aji_act_hook().
02267 { 02268 int status, priority; 02269 struct aji_buddy *buddy; 02270 struct aji_resource *tmp = NULL, *last = NULL, *found = NULL; 02271 char *ver, *node, *descrip, *type; 02272 02273 if (client->state != AJI_CONNECTED) 02274 aji_create_buddy(pak->from->partial, client); 02275 02276 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02277 if (!buddy && pak->from->partial) { 02278 /* allow our jid to be used to log in with another resource */ 02279 if (!strcmp((const char *)pak->from->partial, (const char *)client->jid->partial)) 02280 aji_create_buddy(pak->from->partial, client); 02281 else 02282 ast_log(LOG_NOTICE, "Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial); 02283 return; 02284 } 02285 type = iks_find_attrib(pak->x, "type"); 02286 if (client->component && type &&!strcasecmp("probe", type)) { 02287 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02288 ast_verbose("what i was looking for \n"); 02289 } 02290 ASTOBJ_WRLOCK(buddy); 02291 status = (pak->show) ? pak->show : 6; 02292 priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0"); 02293 tmp = buddy->resources; 02294 descrip = ast_strdup(iks_find_cdata(pak->x, "status")); 02295 02296 while (tmp && pak->from->resource) { 02297 if (!strcasecmp(tmp->resource, pak->from->resource)) { 02298 tmp->status = status; 02299 if (tmp->description) { 02300 ast_free(tmp->description); 02301 } 02302 tmp->description = descrip; 02303 found = tmp; 02304 if (status == 6) { /* Sign off Destroy resource */ 02305 if (last && found->next) { 02306 last->next = found->next; 02307 } else if (!last) { 02308 if (found->next) { 02309 buddy->resources = found->next; 02310 } else { 02311 buddy->resources = NULL; 02312 } 02313 } else if (!found->next) { 02314 if (last) { 02315 last->next = NULL; 02316 } else { 02317 buddy->resources = NULL; 02318 } 02319 } 02320 ast_free(found); 02321 found = NULL; 02322 break; 02323 } 02324 /* resource list is sorted by descending priority */ 02325 if (tmp->priority != priority) { 02326 found->priority = priority; 02327 if (!last && !found->next) { 02328 /* resource was found to be unique, 02329 leave loop */ 02330 break; 02331 } 02332 /* search for resource in our list 02333 and take it out for the moment */ 02334 if (last) { 02335 last->next = found->next; 02336 } else { 02337 buddy->resources = found->next; 02338 } 02339 02340 last = NULL; 02341 tmp = buddy->resources; 02342 if (!buddy->resources) { 02343 buddy->resources = found; 02344 } 02345 /* priority processing */ 02346 while (tmp) { 02347 /* insert resource back according to 02348 its priority value */ 02349 if (found->priority > tmp->priority) { 02350 if (last) { 02351 /* insert within list */ 02352 last->next = found; 02353 } 02354 found->next = tmp; 02355 if (!last) { 02356 /* insert on top */ 02357 buddy->resources = found; 02358 } 02359 break; 02360 } 02361 if (!tmp->next) { 02362 /* insert at the end of the list */ 02363 tmp->next = found; 02364 found->next = NULL; 02365 break; 02366 } 02367 last = tmp; 02368 tmp = tmp->next; 02369 } 02370 } 02371 break; 02372 } 02373 last = tmp; 02374 tmp = tmp->next; 02375 } 02376 02377 /* resource not found in our list, create it */ 02378 if (!found && status != 6 && pak->from->resource) { 02379 found = ast_calloc(1, sizeof(*found)); 02380 02381 if (!found) { 02382 ast_log(LOG_ERROR, "Out of memory!\n"); 02383 return; 02384 } 02385 ast_copy_string(found->resource, pak->from->resource, sizeof(found->resource)); 02386 found->status = status; 02387 found->description = descrip; 02388 found->priority = priority; 02389 found->next = NULL; 02390 last = NULL; 02391 tmp = buddy->resources; 02392 while (tmp) { 02393 if (found->priority > tmp->priority) { 02394 if (last) { 02395 last->next = found; 02396 } 02397 found->next = tmp; 02398 if (!last) { 02399 buddy->resources = found; 02400 } 02401 break; 02402 } 02403 if (!tmp->next) { 02404 tmp->next = found; 02405 break; 02406 } 02407 last = tmp; 02408 tmp = tmp->next; 02409 } 02410 if (!tmp) { 02411 buddy->resources = found; 02412 } 02413 } 02414 02415 ASTOBJ_UNLOCK(buddy); 02416 ASTOBJ_UNREF(buddy, aji_buddy_destroy); 02417 02418 node = iks_find_attrib(iks_find(pak->x, "c"), "node"); 02419 ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"); 02420 02421 /* handle gmail client's special caps:c tag */ 02422 if (!node && !ver) { 02423 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node"); 02424 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver"); 02425 } 02426 02427 /* retrieve capabilites of the new resource */ 02428 if (status != 6 && found && !found->cap) { 02429 found->cap = aji_find_version(node, ver, pak); 02430 if (gtalk_yuck(pak->x)) { /* gtalk should do discover */ 02431 found->cap->jingle = 1; 02432 } 02433 if (found->cap->jingle) { 02434 ast_debug(1, "Special case for google till they support discover.\n"); 02435 } else { 02436 iks *iq, *query; 02437 iq = iks_new("iq"); 02438 query = iks_new("query"); 02439 if (query && iq) { 02440 iks_insert_attrib(iq, "type", "get"); 02441 iks_insert_attrib(iq, "to", pak->from->full); 02442 iks_insert_attrib(iq, "from", client->jid->full); 02443 iks_insert_attrib(iq, "id", client->mid); 02444 ast_aji_increment_mid(client->mid); 02445 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info"); 02446 iks_insert_node(iq, query); 02447 ast_aji_send(client, iq); 02448 } else { 02449 ast_log(LOG_ERROR, "Out of memory.\n"); 02450 } 02451 iks_delete(query); 02452 iks_delete(iq); 02453 } 02454 } 02455 switch (pak->subtype) { 02456 case IKS_TYPE_AVAILABLE: 02457 ast_debug(3, "JABBER: I am available ^_* %i\n", pak->subtype); 02458 break; 02459 case IKS_TYPE_UNAVAILABLE: 02460 ast_debug(3, "JABBER: I am unavailable ^_* %i\n", pak->subtype); 02461 break; 02462 default: 02463 ast_debug(3, "JABBER: Ohh sexy and the wrong type: %i\n", pak->subtype); 02464 } 02465 switch (pak->show) { 02466 case IKS_SHOW_UNAVAILABLE: 02467 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02468 break; 02469 case IKS_SHOW_AVAILABLE: 02470 ast_debug(3, "JABBER: type is available\n"); 02471 break; 02472 case IKS_SHOW_CHAT: 02473 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02474 break; 02475 case IKS_SHOW_AWAY: 02476 ast_debug(3, "JABBER: type is away\n"); 02477 break; 02478 case IKS_SHOW_XA: 02479 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02480 break; 02481 case IKS_SHOW_DND: 02482 ast_debug(3, "JABBER: type: %i subtype %i\n", pak->subtype, pak->show); 02483 break; 02484 default: 02485 ast_debug(3, "JABBER: Kinky! how did that happen %i\n", pak->show); 02486 } 02487 02488 if (found) { 02489 manager_event(EVENT_FLAG_USER, "JabberStatus", 02490 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 02491 "\r\nDescription: %s\r\n", 02492 client->name, pak->from->partial, found->resource, found->status, 02493 found->priority, found->description); 02494 } else { 02495 manager_event(EVENT_FLAG_USER, "JabberStatus", 02496 "Account: %s\r\nJID: %s\r\nStatus: %d\r\n", 02497 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE); 02498 } 02499 }
static int aji_handle_pubsub_error | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 3444 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_send(), ast_log(), ast_test_flag, ASTOBJ_REF, LOG_ERROR, and pubsubflags.
Referenced by aji_init_event_distribution().
03445 { 03446 char *node_name; 03447 char *error; 03448 int error_num; 03449 iks *orig_request; 03450 iks *orig_pubsub = iks_find(pak->x, "pubsub"); 03451 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03452 if (!orig_pubsub) { 03453 ast_log(LOG_ERROR, "Error isn't a PubSub error, why are we here?\n"); 03454 return IKS_FILTER_EAT; 03455 } 03456 orig_request = iks_child(orig_pubsub); 03457 error = iks_find_attrib(iks_find(pak->x, "error"), "code"); 03458 node_name = iks_find_attrib(orig_request, "node"); 03459 if (!sscanf(error, "%30d", &error_num)) { 03460 return IKS_FILTER_EAT; 03461 } 03462 if (error_num > 399 && error_num < 500 && error_num != 404) { 03463 ast_log(LOG_ERROR, 03464 "Error performing operation on PubSub node %s, %s.\n", node_name, error); 03465 return IKS_FILTER_EAT; 03466 } else if (error_num > 499 && error_num < 600) { 03467 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error); 03468 return IKS_FILTER_EAT; 03469 } 03470 03471 if (!strcasecmp(iks_name(orig_request), "publish")) { 03472 iks *request; 03473 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03474 if (iks_find(iks_find(orig_request, "item"), "state")) { 03475 aji_create_pubsub_leaf(client, "device_state", node_name); 03476 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) { 03477 aji_create_pubsub_leaf(client, "message_waiting", node_name); 03478 } 03479 } else { 03480 aji_create_pubsub_node(client, NULL, node_name, NULL); 03481 } 03482 request = aji_pubsub_iq_create(client, "set"); 03483 iks_insert_node(request, orig_pubsub); 03484 ast_aji_send(client, request); 03485 iks_delete(request); 03486 return IKS_FILTER_EAT; 03487 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) { 03488 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03489 aji_create_pubsub_collection(client, node_name); 03490 } else { 03491 aji_create_pubsub_node(client, NULL, node_name, NULL); 03492 } 03493 } 03494 03495 return IKS_FILTER_EAT; 03496 }
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 3233 of file res_jabber.c.
References ast_devstate_val(), ast_eid_cmp(), ast_eid_default, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_RAW, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_log(), ast_str_to_eid(), context, LOG_DEBUG, LOG_ERROR, and strsep().
Referenced by aji_init_event_distribution().
03234 { 03235 char *item_id, *device_state, *context; 03236 int oldmsgs, newmsgs; 03237 iks *item, *item_content; 03238 struct ast_eid pubsub_eid; 03239 struct ast_event *event; 03240 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); 03241 if (!item) { 03242 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); 03243 return IKS_FILTER_EAT; 03244 } 03245 item_id = iks_find_attrib(item, "id"); 03246 item_content = iks_child(item); 03247 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid")); 03248 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) { 03249 ast_log(LOG_DEBUG, "Returning here, eid of incoming event matches ours!\n"); 03250 return IKS_FILTER_EAT; 03251 } 03252 if (!strcasecmp(iks_name(item_content), "state")) { 03253 device_state = iks_find_cdata(item, "state"); 03254 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, 03255 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, 03256 AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, 03257 AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), 03258 AST_EVENT_IE_END))) { 03259 return IKS_FILTER_EAT; 03260 } 03261 } else if (!strcasecmp(iks_name(item_content), "mailbox")) { 03262 context = strsep(&item_id, "@"); 03263 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs); 03264 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs); 03265 if (!(event = ast_event_new(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX, 03266 AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_CONTEXT, 03267 AST_EVENT_IE_PLTYPE_STR, context, AST_EVENT_IE_OLDMSGS, 03268 AST_EVENT_IE_PLTYPE_UINT, oldmsgs, AST_EVENT_IE_NEWMSGS, 03269 AST_EVENT_IE_PLTYPE_UINT, newmsgs, AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, 03270 &pubsub_eid, sizeof(pubsub_eid), AST_EVENT_IE_END))) { 03271 return IKS_FILTER_EAT; 03272 } 03273 } else { 03274 ast_log(LOG_DEBUG, "Don't know how to handle PubSub event of type %s\n", 03275 iks_name(item_content)); 03276 return IKS_FILTER_EAT; 03277 } 03278 ast_event_queue_and_cache(event); 03279 return IKS_FILTER_EAT; 03280 }
static void aji_handle_subscribe | ( | struct aji_client * | client, | |
ikspak * | pak | |||
) | [static] |
Definition at line 2508 of file res_jabber.c.
References AJI_AUTOACCEPT, aji_create_buddy(), aji_set_presence(), ast_aji_send(), ast_log(), ast_test_flag, ast_verbose, ASTOBJ_CONTAINER_FIND, 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().
02509 { 02510 iks *presence = NULL, *status = NULL; 02511 struct aji_buddy* buddy = NULL; 02512 02513 switch (pak->subtype) { 02514 case IKS_TYPE_SUBSCRIBE: 02515 if (ast_test_flag(&client->flags, AJI_AUTOACCEPT)) { 02516 presence = iks_new("presence"); 02517 status = iks_new("status"); 02518 if (presence && status) { 02519 iks_insert_attrib(presence, "type", "subscribed"); 02520 iks_insert_attrib(presence, "to", pak->from->full); 02521 iks_insert_attrib(presence, "from", client->jid->full); 02522 if (pak->id) 02523 iks_insert_attrib(presence, "id", pak->id); 02524 iks_insert_cdata(status, "Asterisk has approved subscription", 0); 02525 iks_insert_node(presence, status); 02526 ast_aji_send(client, presence); 02527 } else { 02528 ast_log(LOG_ERROR, "Unable to allocate nodes\n"); 02529 } 02530 02531 iks_delete(presence); 02532 iks_delete(status); 02533 } 02534 02535 if (client->component) 02536 aji_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), client->status, client->statusmessage); 02537 case IKS_TYPE_SUBSCRIBED: 02538 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 02539 if (!buddy && pak->from->partial) { 02540 aji_create_buddy(pak->from->partial, client); 02541 } 02542 default: 02543 if (option_verbose > 4) { 02544 ast_verbose(VERBOSE_PREFIX_3 "JABBER: This is a subcription of type %i\n", pak->subtype); 02545 } 02546 } 02547 }
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 3204 of file res_jabber.c.
References aji_devstate_cb(), aji_handle_pubsub_error(), aji_handle_pubsub_event(), aji_mwi_cb(), aji_pubsub_subscribe(), ast_enable_distributed_devstate(), AST_EVENT_DEVICE_STATE_CHANGE, ast_event_dump_cache(), AST_EVENT_IE_END, AST_EVENT_MWI, ast_event_subscribe(), device_state_sub, aji_client::f, mwi_sub, and aji_client::pubsub_node.
Referenced by aji_client_connect(), and aji_reload().
03205 { 03206 if (!mwi_sub) { 03207 mwi_sub = ast_event_subscribe(AST_EVENT_MWI, aji_mwi_cb, "aji_mwi_subscription", 03208 client, AST_EVENT_IE_END); 03209 } 03210 if (!device_state_sub) { 03211 if (ast_enable_distributed_devstate()) { 03212 return; 03213 } 03214 device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 03215 aji_devstate_cb, "aji_devstate_subscription", client, AST_EVENT_IE_END); 03216 ast_event_dump_cache(device_state_sub); 03217 } 03218 03219 aji_pubsub_subscribe(client, "device_state"); 03220 aji_pubsub_subscribe(client, "message_waiting"); 03221 iks_filter_add_rule(client->f, aji_handle_pubsub_event, client, IKS_RULE_TYPE, 03222 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->pubsub_node, IKS_RULE_DONE); 03223 iks_filter_add_rule(client->f, aji_handle_pubsub_error, client, IKS_RULE_TYPE, 03224 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE); 03225 03226 }
static int aji_initialize | ( | struct aji_client * | client | ) | [static] |
Definition at line 3098 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().
03099 { 03100 int connected = IKS_NET_NOCONN; 03101 03102 #ifdef HAVE_OPENSSL 03103 /* reset stream flags */ 03104 client->stream_flags = 0; 03105 #endif 03106 /* If it's a component, connect to user, otherwise, connect to server */ 03107 connected = iks_connect_via(client->p, S_OR(client->serverhost, client->jid->server), client->port, client->component ? client->user : client->jid->server); 03108 03109 if (connected == IKS_NET_NOCONN) { 03110 ast_log(LOG_ERROR, "JABBER ERROR: No Connection\n"); 03111 return IKS_HOOK; 03112 } else if (connected == IKS_NET_NODNS) { 03113 ast_log(LOG_ERROR, "JABBER ERROR: No DNS %s for client to %s\n", client->name, 03114 S_OR(client->serverhost, client->jid->server)); 03115 return IKS_HOOK; 03116 } 03117 03118 return IKS_OK; 03119 }
static int aji_io_recv | ( | struct aji_client * | client, | |
char * | buffer, | |||
size_t | buf_len, | |||
int | timeout | |||
) | [static] |
Definition at line 1292 of file res_jabber.c.
References aji_is_secure(), ast_poll, len(), aji_client::p, and aji_client::ssl_session.
Referenced by aji_recv().
01293 { 01294 struct pollfd pfd = { .events = POLLIN }; 01295 int len, res; 01296 01297 #ifdef HAVE_OPENSSL 01298 if (aji_is_secure(client)) { 01299 pfd.fd = SSL_get_fd(client->ssl_session); 01300 if (pfd.fd < 0) { 01301 return -1; 01302 } 01303 } else 01304 #endif /* HAVE_OPENSSL */ 01305 pfd.fd = iks_fd(client->p); 01306 01307 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1); 01308 if (res > 0) { 01309 #ifdef HAVE_OPENSSL 01310 if (aji_is_secure(client)) { 01311 len = SSL_read(client->ssl_session, buffer, buf_len); 01312 } else 01313 #endif /* HAVE_OPENSSL */ 01314 len = recv(pfd.fd, buffer, buf_len, 0); 01315 01316 if (len > 0) { 01317 return len; 01318 } else if (len <= 0) { 01319 return -1; 01320 } 01321 } 01322 return res; 01323 }
static int aji_is_secure | ( | struct aji_client * | client | ) | [static] |
Definition at line 1202 of file res_jabber.c.
References aji_client::stream_flags.
Referenced by aji_act_hook(), aji_io_recv(), aji_send_raw(), and aji_start_sasl().
01203 { 01204 #ifdef HAVE_OPENSSL 01205 return client->stream_flags & SECURE; 01206 #else 01207 return 0; 01208 #endif 01209 }
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 987 of file res_jabber.c.
References aji_client_destroy(), AJI_MAX_RESJIDLEN, args, 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().
00988 { 00989 struct aji_client *client = NULL; 00990 char *s; 00991 char nick[AJI_MAX_RESJIDLEN]; 00992 00993 AST_DECLARE_APP_ARGS(args, 00994 AST_APP_ARG(sender); 00995 AST_APP_ARG(jid); 00996 AST_APP_ARG(nick); 00997 ); 00998 00999 if (!data) { 01000 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01001 return -1; 01002 } 01003 s = ast_strdupa(data); 01004 01005 AST_STANDARD_APP_ARGS(args, s); 01006 if (args.argc < 2 || args.argc > 3) { 01007 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin); 01008 return -1; 01009 } 01010 01011 if (!(client = ast_aji_get_client(args.sender))) { 01012 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01013 return -1; 01014 } 01015 01016 if (strchr(args.jid, '/')) { 01017 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n"); 01018 ASTOBJ_UNREF(client, aji_client_destroy); 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, 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_client_destroy(), AJI_MAX_RESJIDLEN, args, 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 (!(client = ast_aji_get_client(args.sender))) { 01073 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01074 return -1; 01075 } 01076 01077 if (strchr(args.jid, '/')) { 01078 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n"); 01079 ASTOBJ_UNREF(client, aji_client_destroy); 01080 return -1; 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, aji_client_destroy); 01096 return 0; 01097 }
static int aji_load_config | ( | int | reload | ) | [static] |
Definition at line 4505 of file res_jabber.c.
References AJI_AUTOACCEPT, AJI_AUTOPRUNE, AJI_AUTOREGISTER, ast_category_browse(), ast_config_load, ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, debug, globalflags, JABBER_CONFIG, LOG_WARNING, and var.
Referenced by aji_reload().
04506 { 04507 char *cat = NULL; 04508 int debug = 0; 04509 struct ast_config *cfg = NULL; 04510 struct ast_variable *var = NULL; 04511 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 04512 04513 if ((cfg = ast_config_load(JABBER_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 04514 return -1; 04515 } 04516 04517 /* Reset flags to default value */ 04518 ast_set_flag(&globalflags, AJI_AUTOREGISTER | AJI_AUTOACCEPT); 04519 04520 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 04521 ast_log(LOG_WARNING, "No such configuration file %s\n", JABBER_CONFIG); 04522 return 0; 04523 } 04524 04525 cat = ast_category_browse(cfg, NULL); 04526 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 04527 if (!strcasecmp(var->name, "debug")) { 04528 debug = (ast_false(ast_variable_retrieve(cfg, "general", "debug"))) ? 0 : 1; 04529 } else if (!strcasecmp(var->name, "autoprune")) { 04530 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOPRUNE); 04531 } else if (!strcasecmp(var->name, "autoregister")) { 04532 ast_set2_flag(&globalflags, ast_true(var->value), AJI_AUTOREGISTER); 04533 } else if (!strcasecmp(var->name, "collection_nodes")) { 04534 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_XEP0248); 04535 } else if (!strcasecmp(var->name, "pubsub_autocreate")) { 04536 ast_set2_flag(&pubsubflags, ast_true(var->value), AJI_PUBSUB_AUTOCREATE); 04537 } else if (!strcasecmp(var->name, "auth_policy")) { 04538 if (!strcasecmp(var->value, "accept")) { 04539 ast_set_flag(&globalflags, AJI_AUTOACCEPT); 04540 } else { 04541 ast_clear_flag(&globalflags, AJI_AUTOACCEPT); 04542 } 04543 } 04544 } 04545 04546 while (cat) { 04547 if (strcasecmp(cat, "general")) { 04548 var = ast_variable_browse(cfg, cat); 04549 aji_create_client(cat, var, debug); 04550 } 04551 cat = ast_category_browse(cfg, cat); 04552 } 04553 ast_config_destroy(cfg); /* or leak memory */ 04554 return 1; 04555 }
static void aji_log_hook | ( | void * | data, | |
const char * | xmpp, | |||
size_t | size, | |||
int | is_incoming | |||
) | [static] |
Definition at line 1483 of file res_jabber.c.
References 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().
01484 { 01485 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01486 01487 if (!ast_strlen_zero(xmpp)) { 01488 manager_event(EVENT_FLAG_USER, "JabberEvent", "Account: %s\r\nPacket: %s\r\n", client->name, xmpp); 01489 } 01490 01491 if (client->debug) { 01492 if (is_incoming) { 01493 ast_verbose("\nJABBER: %s INCOMING: %s\n", client->name, xmpp); 01494 } else { 01495 if (strlen(xmpp) == 1) { 01496 if (option_debug > 2 && xmpp[0] == ' ') { 01497 ast_verbose("\nJABBER: Keep alive packet\n"); 01498 } 01499 } else { 01500 ast_verbose("\nJABBER: %s OUTGOING: %s\n", client->name, xmpp); 01501 } 01502 } 01503 01504 } 01505 ASTOBJ_UNREF(client, aji_client_destroy); 01506 }
static void aji_message_destroy | ( | struct aji_message * | obj | ) | [static] |
Definition at line 454 of file res_jabber.c.
References ast_free, aji_message::from, and aji_message::message.
Referenced by acf_jabberreceive_read(), aji_client_destroy(), and delete_old_messages().
00455 { 00456 if (obj->from) { 00457 ast_free(obj->from); 00458 } 00459 if (obj->message) { 00460 ast_free(obj->message); 00461 } 00462 ast_free(obj); 00463 }
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 3151 of file res_jabber.c.
References aji_publish_mwi(), 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, context, LOG_DEBUG, and mailbox.
Referenced by aji_init_event_distribution().
03152 { 03153 const char *mailbox; 03154 const char *context; 03155 char oldmsgs[10]; 03156 char newmsgs[10]; 03157 struct aji_client *client; 03158 if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) 03159 { 03160 /* If the event didn't originate from this server, don't send it back out. */ 03161 ast_log(LOG_DEBUG, "Returning here\n"); 03162 return; 03163 } 03164 03165 client = ASTOBJ_REF((struct aji_client *) data); 03166 mailbox = ast_event_get_ie_str(ast_event, AST_EVENT_IE_MAILBOX); 03167 context = ast_event_get_ie_str(ast_event, AST_EVENT_IE_CONTEXT); 03168 snprintf(oldmsgs, sizeof(oldmsgs), "%d", 03169 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_OLDMSGS)); 03170 snprintf(newmsgs, sizeof(newmsgs), "%d", 03171 ast_event_get_ie_uint(ast_event, AST_EVENT_IE_NEWMSGS)); 03172 aji_publish_mwi(client, mailbox, context, oldmsgs, newmsgs); 03173 03174 }
static void aji_pruneregister | ( | struct aji_client * | client | ) | [static] |
Definition at line 2874 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.
02875 { 02876 int res = 0; 02877 iks *removeiq = iks_new("iq"); 02878 iks *removequery = iks_new("query"); 02879 iks *removeitem = iks_new("item"); 02880 iks *send = iks_make_iq(IKS_TYPE_GET, "http://jabber.org/protocol/disco#items"); 02881 if (!client || !removeiq || !removequery || !removeitem || !send) { 02882 ast_log(LOG_ERROR, "Out of memory.\n"); 02883 goto safeout; 02884 } 02885 02886 iks_insert_node(removeiq, removequery); 02887 iks_insert_node(removequery, removeitem); 02888 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 02889 ASTOBJ_RDLOCK(iterator); 02890 /* For an aji_buddy, both AUTOPRUNE and AUTOREGISTER will never 02891 * be called at the same time */ 02892 if (ast_test_flag(&iterator->flags, AJI_AUTOPRUNE)) { /* If autoprune is set on jabber.conf */ 02893 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name, 02894 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX" 02895 " so I am no longer subscribing to your presence.\n")); 02896 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name, 02897 "GoodBye. You are no longer in the Asterisk config file so I am removing" 02898 " your access to my presence.\n")); 02899 iks_insert_attrib(removeiq, "from", client->jid->full); 02900 iks_insert_attrib(removeiq, "type", "set"); 02901 iks_insert_attrib(removequery, "xmlns", "jabber:iq:roster"); 02902 iks_insert_attrib(removeitem, "jid", iterator->name); 02903 iks_insert_attrib(removeitem, "subscription", "remove"); 02904 res = ast_aji_send(client, removeiq); 02905 } else if (ast_test_flag(&iterator->flags, AJI_AUTOREGISTER)) { 02906 res = ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name, 02907 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n")); 02908 ast_clear_flag(&iterator->flags, AJI_AUTOREGISTER); 02909 } 02910 ASTOBJ_UNLOCK(iterator); 02911 }); 02912 02913 safeout: 02914 iks_delete(removeiq); 02915 iks_delete(removequery); 02916 iks_delete(removeitem); 02917 iks_delete(send); 02918 02919 ASTOBJ_CONTAINER_PRUNE_MARKED(&client->buddies, aji_buddy_destroy); 02920 }
static void aji_publish_device_state | ( | struct aji_client * | client, | |
const char * | device, | |||
const char * | device_state | |||
) | [static] |
Publish device state to a PubSub node.
client | the configured XMPP client we use to connect to a XMPP server | |
device | the name of the device whose state to publish | |
device_state | the state to publish |
Definition at line 3379 of file res_jabber.c.
References aji_build_publish_skeleton(), aji_create_pubsub_node(), AJI_PUBSUB_AUTOCREATE, AJI_XEP0248, ast_aji_send(), ast_eid_default, ast_eid_to_str(), ast_test_flag, and pubsubflags.
Referenced by aji_devstate_cb().
03381 { 03382 iks *request = aji_build_publish_skeleton(client, device, "device_state"); 03383 iks *state; 03384 char eid_str[20]; 03385 if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { 03386 if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { 03387 aji_create_pubsub_node(client, "leaf", device, "device_state"); 03388 } else { 03389 aji_create_pubsub_node(client, NULL, device, NULL); 03390 } 03391 } 03392 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03393 state = iks_insert(request, "state"); 03394 iks_insert_attrib(state, "xmlns", "http://asterisk.org"); 03395 iks_insert_attrib(state, "eid", eid_str); 03396 iks_insert_cdata(state, device_state, strlen(device_state)); 03397 ast_aji_send(client, iks_root(request)); 03398 iks_delete(request); 03399 }
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 3408 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().
03410 { 03411 char full_mailbox[AST_MAX_EXTENSION+AST_MAX_CONTEXT]; 03412 char eid_str[20]; 03413 iks *mailbox_node, *request; 03414 snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); 03415 request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting"); 03416 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); 03417 mailbox_node = iks_insert(request, "mailbox"); 03418 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org"); 03419 iks_insert_attrib(mailbox_node, "eid", eid_str); 03420 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs)); 03421 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs)); 03422 ast_aji_send(client, iks_root(request)); 03423 iks_delete(request); 03424 }
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 3432 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().
03433 { 03434 iks *request = iks_new("iq"); 03435 03436 iks_insert_attrib(request, "to", client->pubsub_node); 03437 iks_insert_attrib(request, "from", client->jid->full); 03438 iks_insert_attrib(request, "type", type); 03439 ast_aji_increment_mid(client->mid); 03440 iks_insert_attrib(request, "id", client->mid); 03441 return request; 03442 }
static void aji_pubsub_purge_nodes | ( | struct aji_client * | client, | |
const char * | collection_name | |||
) | [static] |
Definition at line 3647 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().
03648 { 03649 int res = 0; 03650 iks *request = aji_build_node_request(client, collection_name); 03651 ast_aji_send(client, request); 03652 iks_filter_add_rule(client->f, aji_delete_node_list, client, IKS_RULE_TYPE, 03653 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03654 IKS_RULE_DONE); 03655 res = ast_aji_send(client, request); 03656 iks_delete(request); 03657 }
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 3314 of file res_jabber.c.
References aji_pubsub_iq_create(), AJI_XEP0248, ast_aji_send(), ast_test_flag, globalflags, and aji_client::jid.
Referenced by aji_init_event_distribution().
03315 { 03316 iks *request = aji_pubsub_iq_create(client, "set"); 03317 iks *pubsub, *subscribe; 03318 03319 pubsub = iks_insert(request, "pubsub"); 03320 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub"); 03321 subscribe = iks_insert(pubsub, "subscribe"); 03322 iks_insert_attrib(subscribe, "jid", client->jid->partial); 03323 iks_insert_attrib(subscribe, "node", node); 03324 if (ast_test_flag(&globalflags, AJI_XEP0248)) { 03325 iks *options, *x, *sub_options, *sub_type, *sub_depth; 03326 options = iks_insert(pubsub, "options"); 03327 x = iks_insert(options, "x"); 03328 iks_insert_attrib(x, "xmlns", "jabber:x:data"); 03329 iks_insert_attrib(x, "type", "submit"); 03330 sub_options = iks_insert(x, "field"); 03331 iks_insert_attrib(sub_options, "var", "FORM_TYPE"); 03332 iks_insert_attrib(sub_options, "type", "hidden"); 03333 iks_insert_cdata(iks_insert(sub_options, "value"), 03334 "http://jabber.org/protocol/pubsub#subscribe_options", 51); 03335 sub_type = iks_insert(x, "field"); 03336 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type"); 03337 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5); 03338 sub_depth = iks_insert(x, "field"); 03339 iks_insert_attrib(sub_type, "var", "pubsub#subscription_depth"); 03340 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3); 03341 } 03342 ast_aji_send(client, request); 03343 iks_delete(request); 03344 }
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 3541 of file res_jabber.c.
References ast_verbose, ASTOBJ_REF, aji_client::jid, and aji_client::name.
Referenced by aji_request_pubsub_nodes().
03542 { 03543 03544 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 03545 iks *item = NULL; 03546 if (iks_has_children(pak->query)) { 03547 item = iks_first_tag(pak->query); 03548 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial, 03549 iks_find_attrib(item, "node")); 03550 while ((item = iks_next_tag(item))) { 03551 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node")); 03552 } 03553 } 03554 if (item) { 03555 iks_delete(item); 03556 } 03557 return IKS_FILTER_EAT; 03558 }
static int aji_reconnect | ( | struct aji_client * | client | ) | [static] |
Definition at line 3014 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().
03015 { 03016 int res = 0; 03017 03018 if (client->state) { 03019 client->state = AJI_DISCONNECTED; 03020 } 03021 client->timeout = 50; 03022 if (client->p) { 03023 iks_parser_reset(client->p); 03024 } 03025 if (client->authorized) { 03026 client->authorized = 0; 03027 } 03028 03029 res = aji_initialize(client); 03030 03031 return res; 03032 }
static int aji_recv | ( | struct aji_client * | client, | |
int | timeout | |||
) | [static] |
Definition at line 1337 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().
01338 { 01339 int len, ret; 01340 char buf[NET_IO_BUF_SIZE - 1]; 01341 char newbuf[NET_IO_BUF_SIZE - 1]; 01342 int pos = 0; 01343 int newbufpos = 0; 01344 unsigned char c; 01345 01346 memset(buf, 0, sizeof(buf)); 01347 memset(newbuf, 0, sizeof(newbuf)); 01348 01349 while (1) { 01350 len = aji_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout); 01351 if (len < 0) return IKS_NET_RWERR; 01352 if (len == 0) return IKS_NET_EXPIRED; 01353 buf[len] = '\0'; 01354 01355 /* our iksemel parser won't work as expected if we feed 01356 it with XML packets that contain multiple whitespace 01357 characters between tags */ 01358 while (pos < len) { 01359 c = buf[pos]; 01360 /* if we stumble on the ending tag character, 01361 we skip any whitespace that follows it*/ 01362 if (c == '>') { 01363 while (isspace(buf[pos+1])) { 01364 pos++; 01365 } 01366 } 01367 newbuf[newbufpos] = c; 01368 newbufpos ++; 01369 pos++; 01370 } 01371 pos = 0; 01372 newbufpos = 0; 01373 01374 /* Log the message here, because iksemel's logHook is 01375 unaccessible */ 01376 aji_log_hook(client, buf, len, 1); 01377 01378 /* let iksemel deal with the string length, 01379 and reset our buffer */ 01380 ret = iks_parse(client->p, newbuf, 0, 0); 01381 memset(newbuf, 0, sizeof(newbuf)); 01382 01383 switch (ret) { 01384 case IKS_NOMEM: 01385 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n"); 01386 break; 01387 case IKS_BADXML: 01388 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n"); 01389 break; 01390 case IKS_HOOK: 01391 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n"); 01392 break; 01393 } 01394 if (ret != IKS_OK) { 01395 return ret; 01396 } 01397 ast_debug(3, "XML parsing successful\n"); 01398 } 01399 return IKS_OK; 01400 }
static void * aji_recv_loop | ( | void * | data | ) | [static] |
Definition at line 2708 of file res_jabber.c.
References aji_client_destroy(), AJI_CONNECTED, AJI_DISCONNECTING, aji_reconnect(), aji_recv(), aji_send_raw(), 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().
02709 { 02710 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 02711 int res = IKS_HOOK; 02712 02713 while (res != IKS_OK) { 02714 ast_debug(3, "JABBER: Connecting.\n"); 02715 res = aji_reconnect(client); 02716 sleep(4); 02717 } 02718 02719 do { 02720 if (res == IKS_NET_RWERR || client->timeout == 0) { 02721 while (res != IKS_OK) { 02722 ast_debug(3, "JABBER: reconnecting.\n"); 02723 res = aji_reconnect(client); 02724 sleep(4); 02725 } 02726 } 02727 02728 res = aji_recv(client, 1); 02729 02730 if (client->state == AJI_DISCONNECTING) { 02731 ast_debug(2, "Ending our Jabber client's thread due to a disconnect\n"); 02732 pthread_exit(NULL); 02733 } 02734 02735 /* Decrease timeout if no data received, and delete 02736 * old messages globally */ 02737 if (res == IKS_NET_EXPIRED) { 02738 client->timeout--; 02739 delete_old_messages_all(client); 02740 } 02741 if (res == IKS_HOOK) { 02742 ast_log(LOG_WARNING, "JABBER: Got hook event.\n"); 02743 } else if (res == IKS_NET_TLSFAIL) { 02744 ast_log(LOG_ERROR, "JABBER: Failure in TLS.\n"); 02745 } else if (client->timeout == 0 && client->state == AJI_CONNECTED) { 02746 res = client->keepalive ? aji_send_raw(client, " ") : IKS_OK; 02747 if (res == IKS_OK) { 02748 client->timeout = 50; 02749 } else { 02750 ast_log(LOG_WARNING, "JABBER: Network Timeout\n"); 02751 } 02752 } else if (res == IKS_NET_RWERR) { 02753 ast_log(LOG_WARNING, "JABBER: socket read error\n"); 02754 } 02755 } while (client); 02756 ASTOBJ_UNREF(client, aji_client_destroy); 02757 return 0; 02758 }
static int aji_register_approve_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1788 of file res_jabber.c.
References 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().
01789 { 01790 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01791 iks *iq = NULL, *presence = NULL, *x = NULL; 01792 01793 iq = iks_new("iq"); 01794 presence = iks_new("presence"); 01795 x = iks_new("x"); 01796 if (client && iq && presence && x) { 01797 if (!iks_find(pak->query, "remove")) { 01798 iks_insert_attrib(iq, "from", client->jid->full); 01799 iks_insert_attrib(iq, "to", pak->from->full); 01800 iks_insert_attrib(iq, "id", pak->id); 01801 iks_insert_attrib(iq, "type", "result"); 01802 ast_aji_send(client, iq); 01803 01804 iks_insert_attrib(presence, "from", client->jid->full); 01805 iks_insert_attrib(presence, "to", pak->from->partial); 01806 iks_insert_attrib(presence, "id", client->mid); 01807 ast_aji_increment_mid(client->mid); 01808 iks_insert_attrib(presence, "type", "subscribe"); 01809 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update"); 01810 iks_insert_node(presence, x); 01811 ast_aji_send(client, presence); 01812 } 01813 } else { 01814 ast_log(LOG_ERROR, "Out of memory.\n"); 01815 } 01816 01817 iks_delete(iq); 01818 iks_delete(presence); 01819 iks_delete(x); 01820 01821 ASTOBJ_UNREF(client, aji_client_destroy); 01822 return IKS_FILTER_EAT; 01823 }
static int aji_register_query_handler | ( | void * | data, | |
ikspak * | pak | |||
) | [static] |
Definition at line 1831 of file res_jabber.c.
References 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().
01832 { 01833 struct aji_client *client = ASTOBJ_REF((struct aji_client *) data); 01834 struct aji_buddy *buddy = NULL; 01835 char *node = NULL; 01836 iks *iq = NULL, *query = NULL; 01837 01838 client = (struct aji_client *) data; 01839 01840 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, pak->from->partial); 01841 if (!buddy) { 01842 iks *error = NULL, *notacceptable = NULL; 01843 01844 ast_log(LOG_ERROR, "Someone.... %s tried to register but they aren't allowed\n", pak->from->partial); 01845 iq = iks_new("iq"); 01846 query = iks_new("query"); 01847 error = iks_new("error"); 01848 notacceptable = iks_new("not-acceptable"); 01849 if (iq && query && error && notacceptable) { 01850 iks_insert_attrib(iq, "type", "error"); 01851 iks_insert_attrib(iq, "from", client->user); 01852 iks_insert_attrib(iq, "to", pak->from->full); 01853 iks_insert_attrib(iq, "id", pak->id); 01854 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01855 iks_insert_attrib(error, "code" , "406"); 01856 iks_insert_attrib(error, "type", "modify"); 01857 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas"); 01858 iks_insert_node(iq, query); 01859 iks_insert_node(iq, error); 01860 iks_insert_node(error, notacceptable); 01861 ast_aji_send(client, iq); 01862 } else { 01863 ast_log(LOG_ERROR, "Out of memory.\n"); 01864 } 01865 01866 iks_delete(error); 01867 iks_delete(notacceptable); 01868 } else if (!(node = iks_find_attrib(pak->query, "node"))) { 01869 iks *instructions = NULL; 01870 char *explain = "Welcome to Asterisk - the Open Source PBX.\n"; 01871 iq = iks_new("iq"); 01872 query = iks_new("query"); 01873 instructions = iks_new("instructions"); 01874 if (iq && query && instructions && client) { 01875 iks_insert_attrib(iq, "from", client->user); 01876 iks_insert_attrib(iq, "to", pak->from->full); 01877 iks_insert_attrib(iq, "id", pak->id); 01878 iks_insert_attrib(iq, "type", "result"); 01879 iks_insert_attrib(query, "xmlns", "jabber:iq:register"); 01880 iks_insert_cdata(instructions, explain, 0); 01881 iks_insert_node(iq, query); 01882 iks_insert_node(query, instructions); 01883 ast_aji_send(client, iq); 01884 } else { 01885 ast_log(LOG_ERROR, "Out of memory.\n"); 01886 } 01887 01888 iks_delete(instructions); 01889 } 01890 iks_delete(iq); 01891 iks_delete(query); 01892 ASTOBJ_UNREF(client, aji_client_destroy); 01893 return IKS_FILTER_EAT; 01894 }
static int aji_reload | ( | int | reload | ) | [static] |
Definition at line 4641 of file res_jabber.c.
References aji_client_destroy(), AJI_CONNECTING, AJI_DISCONNECTED, aji_get_roster(), aji_init_event_distribution(), aji_load_config(), aji_recv_loop(), ast_log(), ast_pthread_create_background, ASTOBJ_CONTAINER_MARKALL, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, clients, and LOG_ERROR.
Referenced by aji_do_reload(), load_module(), and reload().
04642 { 04643 int res; 04644 04645 ASTOBJ_CONTAINER_MARKALL(&clients); 04646 if (!(res = aji_load_config(reload))) { 04647 ast_log(LOG_ERROR, "JABBER: Failed to load config.\n"); 04648 return 0; 04649 } else if (res == -1) 04650 return 1; 04651 04652 ASTOBJ_CONTAINER_PRUNE_MARKED(&clients, aji_client_destroy); 04653 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04654 ASTOBJ_RDLOCK(iterator); 04655 if (iterator->state == AJI_DISCONNECTED) { 04656 if (!iterator->thread) 04657 ast_pthread_create_background(&iterator->thread, NULL, aji_recv_loop, iterator); 04658 } else if (iterator->state == AJI_CONNECTING) { 04659 aji_get_roster(iterator); 04660 if (iterator->distribute_events) { 04661 aji_init_event_distribution(iterator); 04662 } 04663 } 04664 04665 ASTOBJ_UNLOCK(iterator); 04666 }); 04667 04668 return 1; 04669 }
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 3504 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().
03505 { 03506 int res = 0; 03507 iks *request = aji_build_node_request(client, collection); 03508 03509 iks_filter_add_rule(client->f, aji_receive_node_list, client, IKS_RULE_TYPE, 03510 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, 03511 IKS_RULE_DONE); 03512 res = ast_aji_send(client, request); 03513 iks_delete(request); 03514 03515 }
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_get_client(), ast_aji_send_chat(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), 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 return 0; 01137 }
static int aji_send_header | ( | struct aji_client * | client, | |
const char * | to | |||
) | [static] |
Definition at line 1409 of file res_jabber.c.
References aji_send_raw(), len(), and aji_client::name_space.
Referenced by aji_act_hook(), and aji_tls_handshake().
01410 { 01411 char *msg; 01412 int len, err; 01413 01414 len = 91 + strlen(client->name_space) + 6 + strlen(to) + 16 + 1; 01415 msg = iks_malloc(len); 01416 if (!msg) 01417 return IKS_NOMEM; 01418 sprintf(msg, "<?xml version='1.0'?>" 01419 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 01420 "%s' to='%s' version='1.0'>", client->name_space, to); 01421 err = aji_send_raw(client, msg); 01422 iks_free(msg); 01423 if (err != IKS_OK) 01424 return err; 01425 01426 return IKS_OK; 01427 }
static int aji_send_raw | ( | struct aji_client * | client, | |
const char * | xmlstr | |||
) | [static] |
Definition at line 1449 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().
01450 { 01451 int ret; 01452 #ifdef HAVE_OPENSSL 01453 int len = strlen(xmlstr); 01454 01455 if (aji_is_secure(client)) { 01456 ret = SSL_write(client->ssl_session, xmlstr, len); 01457 if (ret) { 01458 /* Log the message here, because iksemel's logHook is 01459 unaccessible */ 01460 aji_log_hook(client, xmlstr, len, 0); 01461 return IKS_OK; 01462 } 01463 } 01464 #endif 01465 /* If needed, data will be sent unencrypted, and logHook will 01466 be called inside iks_send_raw */ 01467 ret = iks_send_raw(client->p, xmlstr); 01468 if (ret != IKS_OK) { 01469 return ret; 01470 } 01471 01472 return IKS_OK; 01473 }
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 2584 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().
02585 { 02586 int res = 0; 02587 iks *message_packet = NULL; 02588 char from[AJI_MAX_JIDLEN]; 02589 /* the nickname is used only in component mode */ 02590 if (nick && client->component) { 02591 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 02592 } else { 02593 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 02594 } 02595 02596 if (client->state != AJI_CONNECTED) { 02597 ast_log(LOG_WARNING, "JABBER: Not connected can't send\n"); 02598 return -1; 02599 } 02600 02601 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message); 02602 if (!message_packet) { 02603 ast_log(LOG_ERROR, "Out of memory.\n"); 02604 return -1; 02605 } 02606 iks_insert_attrib(message_packet, "from", from); 02607 res = ast_aji_send(client, message_packet); 02608 iks_delete(message_packet); 02609 02610 return res; 02611 }
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 1146 of file res_jabber.c.
References aji_client_destroy(), AJI_MAX_RESJIDLEN, args, 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().
01147 { 01148 struct aji_client *client = NULL; 01149 char *s; 01150 char nick[AJI_MAX_RESJIDLEN]; 01151 int res = 0; 01152 AST_DECLARE_APP_ARGS(args, 01153 AST_APP_ARG(sender); 01154 AST_APP_ARG(groupchat); 01155 AST_APP_ARG(message); 01156 AST_APP_ARG(nick); 01157 ); 01158 01159 if (!data) { 01160 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01161 return -1; 01162 } 01163 s = ast_strdupa(data); 01164 01165 AST_STANDARD_APP_ARGS(args, s); 01166 if (args.argc < 3 || args.argc > 4) { 01167 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup); 01168 return -1; 01169 } 01170 01171 if (!(client = ast_aji_get_client(args.sender))) { 01172 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender); 01173 return -1; 01174 } 01175 01176 if (ast_strlen_zero(args.nick) || args.argc == 3) { 01177 if (client->component) { 01178 sprintf(nick, "asterisk"); 01179 } else { 01180 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", client->jid->user); 01181 } 01182 } else { 01183 snprintf(nick, AJI_MAX_RESJIDLEN, "%s", args.nick); 01184 } 01185 01186 if (strchr(args.groupchat, '@') && !ast_strlen_zero(args.message)) { 01187 res = ast_aji_send_groupchat(client, nick, args.groupchat, args.message); 01188 } 01189 01190 ASTOBJ_UNREF(client, aji_client_destroy); 01191 if (res != IKS_OK) { 01192 return -1; 01193 } 01194 return 0; 01195 }
static int aji_set_group_presence | ( | struct aji_client * | client, | |
char * | room, | |||
int | level, | |||
char * | nick, | |||
char * | desc | |||
) | [static] |
Definition at line 3968 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().
03969 { 03970 int res = 0; 03971 iks *presence = NULL, *x = NULL; 03972 char from[AJI_MAX_JIDLEN]; 03973 char roomid[AJI_MAX_JIDLEN]; 03974 03975 presence = iks_make_pres(level, NULL); 03976 x = iks_new("x"); 03977 03978 if (client->component) { 03979 snprintf(from, AJI_MAX_JIDLEN, "%s@%s/%s", nick, client->jid->full, nick); 03980 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick); 03981 } else { 03982 snprintf(from, AJI_MAX_JIDLEN, "%s", client->jid->full); 03983 snprintf(roomid, AJI_MAX_JIDLEN, "%s/%s", room, nick ? nick : client->jid->user); 03984 } 03985 03986 if (!presence || !x || !client) { 03987 ast_log(LOG_ERROR, "Out of memory.\n"); 03988 res = -1; 03989 goto safeout; 03990 } else { 03991 iks_insert_attrib(presence, "to", roomid); 03992 iks_insert_attrib(presence, "from", from); 03993 iks_insert_attrib(x, "xmlns", MUC_NS); 03994 iks_insert_node(presence, x); 03995 res = ast_aji_send(client, presence); 03996 } 03997 03998 safeout: 03999 iks_delete(presence); 04000 iks_delete(x); 04001 return res; 04002 }
static void aji_set_presence | ( | struct aji_client * | client, | |
char * | to, | |||
char * | from, | |||
int | level, | |||
char * | desc | |||
) | [static] |
Definition at line 3925 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().
03926 { 03927 int res = 0; 03928 iks *presence = iks_make_pres(level, desc); 03929 iks *cnode = iks_new("c"); 03930 iks *priority = iks_new("priority"); 03931 char priorityS[10]; 03932 03933 if (presence && cnode && client && priority) { 03934 if (to) { 03935 iks_insert_attrib(presence, "to", to); 03936 } 03937 if (from) { 03938 iks_insert_attrib(presence, "from", from); 03939 } 03940 snprintf(priorityS, sizeof(priorityS), "%d", client->priority); 03941 iks_insert_cdata(priority, priorityS, strlen(priorityS)); 03942 iks_insert_node(presence, priority); 03943 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps"); 03944 iks_insert_attrib(cnode, "ver", "asterisk-xmpp"); 03945 iks_insert_attrib(cnode, "ext", "voice-v1"); 03946 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps"); 03947 iks_insert_node(presence, cnode); 03948 res = ast_aji_send(client, presence); 03949 } else { 03950 ast_log(LOG_ERROR, "Out of memory.\n"); 03951 } 03952 03953 iks_delete(cnode); 03954 iks_delete(presence); 03955 iks_delete(priority); 03956 }
static char * aji_show_buddies | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4120 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.
04121 { 04122 struct aji_resource *resource; 04123 struct aji_client *client; 04124 04125 switch (cmd) { 04126 case CLI_INIT: 04127 e->command = "jabber show buddies"; 04128 e->usage = 04129 "Usage: jabber show buddies\n" 04130 " Shows buddy lists of our clients\n"; 04131 return NULL; 04132 case CLI_GENERATE: 04133 return NULL; 04134 } 04135 04136 ast_cli(a->fd, "Jabber buddy lists\n"); 04137 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04138 ast_cli(a->fd, "Client: %s\n", iterator->user); 04139 client = iterator; 04140 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04141 ASTOBJ_RDLOCK(iterator); 04142 ast_cli(a->fd, "\tBuddy:\t%s\n", iterator->name); 04143 if (!iterator->resources) 04144 ast_cli(a->fd, "\t\tResource: None\n"); 04145 for (resource = iterator->resources; resource; resource = resource->next) { 04146 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource); 04147 if (resource->cap) { 04148 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->cap->parent->node); 04149 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->cap->version); 04150 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->cap->jingle ? "yes" : "no"); 04151 } 04152 ast_cli(a->fd, "\t\tStatus: %d\n", resource->status); 04153 ast_cli(a->fd, "\t\tPriority: %d\n", resource->priority); 04154 } 04155 ASTOBJ_UNLOCK(iterator); 04156 }); 04157 iterator = client; 04158 }); 04159 return CLI_SUCCESS; 04160 }
static char * aji_show_clients | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4074 of file res_jabber.c.
References AJI_CONNECTED, AJI_CONNECTING, AJI_DISCONNECTED, ast_cli(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, clients, ast_cli_entry::command, ast_cli_args::fd, status, and ast_cli_entry::usage.
04075 { 04076 char *status; 04077 int count = 0; 04078 04079 switch (cmd) { 04080 case CLI_INIT: 04081 e->command = "jabber show connections"; 04082 e->usage = 04083 "Usage: jabber show connections\n" 04084 " Shows state of client and component connections\n"; 04085 return NULL; 04086 case CLI_GENERATE: 04087 return NULL; 04088 } 04089 04090 ast_cli(a->fd, "Jabber Users and their status:\n"); 04091 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04092 ASTOBJ_RDLOCK(iterator); 04093 count++; 04094 switch (iterator->state) { 04095 case AJI_DISCONNECTED: 04096 status = "Disconnected"; 04097 break; 04098 case AJI_CONNECTING: 04099 status = "Connecting"; 04100 break; 04101 case AJI_CONNECTED: 04102 status = "Connected"; 04103 break; 04104 default: 04105 status = "Unknown"; 04106 } 04107 ast_cli(a->fd, " [%s] %s - %s\n", iterator->name, iterator->user, status); 04108 ASTOBJ_UNLOCK(iterator); 04109 }); 04110 ast_cli(a->fd, "----\n"); 04111 ast_cli(a->fd, " Number of users: %d\n", count); 04112 return CLI_SUCCESS; 04113 }
static int aji_start_sasl | ( | struct aji_client * | client, | |
enum ikssasltype | type, | |||
char * | username, | |||
char * | pass | |||
) | [static] |
Definition at line 1518 of file res_jabber.c.
References aji_is_secure(), ast_aji_send(), ast_base64encode(), ast_log(), base64, len(), LOG_ERROR, and aji_client::p.
Referenced by aji_act_hook().
01519 { 01520 iks *x = NULL; 01521 int len; 01522 char *s; 01523 char *base64; 01524 01525 /* trigger SASL DIGEST-MD5 only over an unsecured connection. 01526 iks_start_sasl is an iksemel API function and relies on GnuTLS, 01527 whereas we use OpenSSL */ 01528 if ((type & IKS_STREAM_SASL_MD5) && !aji_is_secure(client)) 01529 return iks_start_sasl(client->p, IKS_SASL_DIGEST_MD5, username, pass); 01530 if (!(type & IKS_STREAM_SASL_PLAIN)) { 01531 ast_log(LOG_ERROR, "Server does not support SASL PLAIN authentication\n"); 01532 return IKS_NET_NOTSUPP; 01533 } 01534 01535 x = iks_new("auth"); 01536 if (!x) { 01537 ast_log(LOG_ERROR, "Out of memory.\n"); 01538 return IKS_NET_NOTSUPP; 01539 } 01540 01541 iks_insert_attrib(x, "xmlns", IKS_NS_XMPP_SASL); 01542 len = strlen(username) + strlen(pass) + 3; 01543 s = alloca(len); 01544 base64 = alloca((len + 2) * 4 / 3); 01545 iks_insert_attrib(x, "mechanism", "PLAIN"); 01546 snprintf(s, len, "%c%s%c%s", 0, username, 0, pass); 01547 01548 /* exclude the NULL training byte from the base64 encoding operation 01549 as some XMPP servers will refuse it. 01550 The format for authentication is [authzid]\0authcid\0password 01551 not [authzid]\0authcid\0password\0 */ 01552 ast_base64encode(base64, (const unsigned char *) s, len - 1, (len + 2) * 4 / 3); 01553 iks_insert_cdata(x, base64, 0); 01554 ast_aji_send(client, x); 01555 iks_delete(x); 01556 01557 return IKS_OK; 01558 }
static int aji_start_tls | ( | struct aji_client * | client | ) | [static] |
Definition at line 1219 of file res_jabber.c.
References aji_client::p, and aji_client::stream_flags.
Referenced by aji_act_hook().
01220 { 01221 int ret; 01222 01223 /* This is sent not encrypted */ 01224 if ((ret = iks_send_raw(client->p, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"))) { 01225 return ret; 01226 } 01227 01228 client->stream_flags |= TRY_SECURE; 01229 return IKS_OK; 01230 }
static int aji_status_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Definition at line 623 of file res_jabber.c.
References aji_find_resource(), args, 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, 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().
00624 { 00625 struct aji_client *client = NULL; 00626 struct aji_buddy *buddy = NULL; 00627 struct aji_resource *r = NULL; 00628 char *s = NULL; 00629 int stat = 7; 00630 char status[2]; 00631 static int deprecation_warning = 0; 00632 AST_DECLARE_APP_ARGS(args, 00633 AST_APP_ARG(sender); 00634 AST_APP_ARG(jid); 00635 AST_APP_ARG(variable); 00636 ); 00637 AST_DECLARE_APP_ARGS(jid, 00638 AST_APP_ARG(screenname); 00639 AST_APP_ARG(resource); 00640 ); 00641 00642 if (deprecation_warning++ % 10 == 0) { 00643 ast_log(LOG_WARNING, "JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n"); 00644 } 00645 00646 if (!data) { 00647 ast_log(LOG_ERROR, "Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n"); 00648 return 0; 00649 } 00650 s = ast_strdupa(data); 00651 AST_STANDARD_APP_ARGS(args, s); 00652 00653 if (args.argc != 3) { 00654 ast_log(LOG_ERROR, "JabberStatus() requires 3 arguments.\n"); 00655 return -1; 00656 } 00657 00658 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/'); 00659 if (jid.argc < 1 || jid.argc > 2) { 00660 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid); 00661 return -1; 00662 } 00663 00664 if (!(client = ast_aji_get_client(args.sender))) { 00665 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender); 00666 return -1; 00667 } 00668 buddy = ASTOBJ_CONTAINER_FIND(&client->buddies, jid.screenname); 00669 if (!buddy) { 00670 ast_log(LOG_WARNING, "Could not find buddy in list: '%s'\n", jid.screenname); 00671 return -1; 00672 } 00673 r = aji_find_resource(buddy, jid.resource); 00674 if (!r && buddy->resources) { 00675 r = buddy->resources; 00676 } 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 char * aji_test | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 4167 of file res_jabber.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_aji_send_chat(), ast_cli(), ast_verbose, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, aji_client::buddies, aji_resource::cap, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, clients, ast_cli_entry::command, aji_resource::description, ast_cli_args::fd, aji_version::jingle, name, aji_resource::next, aji_capabilities::node, aji_version::parent, aji_resource::priority, aji_resource::resource, S_OR, aji_resource::status, ast_cli_entry::usage, and aji_version::version.
04168 { 04169 struct aji_client *client; 04170 struct aji_resource *resource; 04171 const char *name; 04172 struct aji_message *tmp; 04173 04174 switch (cmd) { 04175 case CLI_INIT: 04176 e->command = "jabber test"; 04177 e->usage = 04178 "Usage: jabber test <connection>\n" 04179 " Sends test message for debugging purposes. A specific client\n" 04180 " as configured in jabber.conf must be specified.\n"; 04181 return NULL; 04182 case CLI_GENERATE: 04183 return NULL; 04184 } 04185 04186 if (a->argc != 3) { 04187 return CLI_SHOWUSAGE; 04188 } 04189 name = a->argv[2]; 04190 04191 if (!(client = ASTOBJ_CONTAINER_FIND(&clients, name))) { 04192 ast_cli(a->fd, "Unable to find client '%s'!\n", name); 04193 return CLI_FAILURE; 04194 } 04195 04196 /* XXX Does Matt really want everyone to use his personal address for tests? */ /* XXX yes he does */ 04197 ast_aji_send_chat(client, "mogorman@astjab.org", "blahblah"); 04198 ASTOBJ_CONTAINER_TRAVERSE(&client->buddies, 1, { 04199 ASTOBJ_RDLOCK(iterator); 04200 ast_verbose("User: %s\n", iterator->name); 04201 for (resource = iterator->resources; resource; resource = resource->next) { 04202 ast_verbose("Resource: %s\n", resource->resource); 04203 if (resource->cap) { 04204 ast_verbose(" client: %s\n", resource->cap->parent->node); 04205 ast_verbose(" version: %s\n", resource->cap->version); 04206 ast_verbose(" Jingle Capable: %d\n", resource->cap->jingle); 04207 } 04208 ast_verbose(" Priority: %d\n", resource->priority); 04209 ast_verbose(" Status: %d\n", resource->status); 04210 ast_verbose(" Message: %s\n", S_OR(resource->description, "")); 04211 } 04212 ASTOBJ_UNLOCK(iterator); 04213 }); 04214 ast_verbose("\nOooh a working message stack!\n"); 04215 AST_LIST_LOCK(&client->messages); 04216 AST_LIST_TRAVERSE(&client->messages, tmp, list) { 04217 //ast_verbose(" Message from: %s with id %s @ %s %s\n",tmp->from, S_OR(tmp->id,""), ctime(&tmp->arrived), S_OR(tmp->message, "")); 04218 } 04219 AST_LIST_UNLOCK(&client->messages); 04220 ASTOBJ_UNREF(client, aji_client_destroy); 04221 04222 return CLI_SUCCESS; 04223 }
static int aji_tls_handshake | ( | struct aji_client * | client | ) | [static] |
Definition at line 1238 of file res_jabber.c.
References aji_send_header(), ast_debug, aji_client::jid, aji_client::p, aji_client::ssl_context, aji_client::ssl_method, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by aji_act_hook().
01239 { 01240 int ret; 01241 int sock; 01242 01243 ast_debug(1, "Starting TLS handshake\n"); 01244 01245 /* Choose an SSL/TLS protocol version, create SSL_CTX */ 01246 client->ssl_method = SSLv3_method(); 01247 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) { 01248 return IKS_NET_TLSFAIL; 01249 } 01250 01251 /* Create new SSL session */ 01252 if (!(client->ssl_session = SSL_new(client->ssl_context))) { 01253 return IKS_NET_TLSFAIL; 01254 } 01255 01256 /* Enforce TLS on our XMPP connection */ 01257 sock = iks_fd(client->p); 01258 if (!(ret = SSL_set_fd(client->ssl_session, sock))) { 01259 return IKS_NET_TLSFAIL; 01260 } 01261 01262 /* Perform SSL handshake */ 01263 if (!(ret = SSL_connect(client->ssl_session))) { 01264 return IKS_NET_TLSFAIL; 01265 } 01266 01267 client->stream_flags &= (~TRY_SECURE); 01268 client->stream_flags |= SECURE; 01269 01270 /* Sent over the established TLS connection */ 01271 if ((ret = aji_send_header(client, client->jid->server)) != IKS_OK) { 01272 return IKS_NET_TLSFAIL; 01273 } 01274 01275 ast_debug(1, "TLS started with server\n"); 01276 01277 return IKS_OK; 01278 }
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 2621 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02622 { 02623 int res = 0; 02624 iks *iq = NULL; 02625 iq = iks_new("iq"); 02626 02627 if (iq && client) { 02628 iks_insert_attrib(iq, "type", "get"); 02629 iks_insert_attrib(iq, "to", server); 02630 iks_insert_attrib(iq, "id", client->mid); 02631 ast_aji_increment_mid(client->mid); 02632 ast_aji_send(client, iq); 02633 } else { 02634 ast_log(LOG_ERROR, "Out of memory.\n"); 02635 } 02636 02637 iks_delete(iq); 02638 02639 return res; 02640 }
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 3126 of file res_jabber.c.
References aji_client_destroy(), ast_verb, ASTOBJ_UNREF, aji_client::p, aji_client::ssl_context, aji_client::ssl_session, and aji_client::stream_flags.
Referenced by unload_module().
03127 { 03128 if (client) { 03129 ast_verb(4, "JABBER: Disconnecting\n"); 03130 #ifdef HAVE_OPENSSL 03131 if (client->stream_flags & SECURE) { 03132 SSL_shutdown(client->ssl_session); 03133 SSL_CTX_free(client->ssl_context); 03134 SSL_free(client->ssl_session); 03135 } 03136 #endif 03137 iks_disconnect(client->p); 03138 iks_parser_delete(client->p); 03139 ASTOBJ_UNREF(client, aji_client_destroy); 03140 } 03141 03142 return 1; 03143 }
struct aji_client* ast_aji_get_client | ( | const char * | name | ) |
grab a aji_client structure by label name or JID (without the resource string)
name | label or JID |
Definition at line 4563 of file res_jabber.c.
References ast_strdupa, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_TRAVERSE, clients, and strsep().
Referenced by acf_jabberreceive_read(), acf_jabberstatus_read(), aji_join_exec(), aji_leave_exec(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), gtalk_create_member(), gtalk_newcall(), gtalk_request(), jingle_create_member(), jingle_newcall(), jingle_request(), and manager_jabber_send().
04564 { 04565 struct aji_client *client = NULL; 04566 char *aux = NULL; 04567 04568 client = ASTOBJ_CONTAINER_FIND(&clients, name); 04569 if (!client && strchr(name, '@')) { 04570 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04571 aux = ast_strdupa(iterator->user); 04572 if (strchr(aux, '/')) { 04573 /* strip resource for comparison */ 04574 aux = strsep(&aux, "/"); 04575 } 04576 if (!strncasecmp(aux, name, strlen(aux))) { 04577 client = iterator; 04578 } 04579 }); 04580 } 04581 04582 return client; 04583 }
struct aji_client_container* ast_aji_get_clients | ( | void | ) |
Definition at line 4585 of file res_jabber.c.
References clients.
04586 { 04587 return &clients; 04588 }
void ast_aji_increment_mid | ( | char * | mid | ) |
increments the mid field for messages and other events.
mid | char. |
Definition at line 2765 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().
02766 { 02767 int i = 0; 02768 02769 for (i = strlen(mid) - 1; i >= 0; i--) { 02770 if (mid[i] != 'z') { 02771 mid[i] = mid[i] + 1; 02772 i = 0; 02773 } else 02774 mid[i] = 'a'; 02775 } 02776 }
int ast_aji_invite_chat | ( | struct aji_client * | client, | |
char * | user, | |||
char * | room, | |||
char * | message | |||
) |
invite to a chatroom.
client | the configured XMPP client we use to connect to a XMPP server | |
user | ||
room | ||
message |
Definition at line 2673 of file res_jabber.c.
References ast_aji_increment_mid(), ast_aji_send(), ast_log(), LOG_ERROR, and aji_client::mid.
02674 { 02675 int res = 0; 02676 iks *invite, *body, *namespace; 02677 02678 invite = iks_new("message"); 02679 body = iks_new("body"); 02680 namespace = iks_new("x"); 02681 if (client && invite && body && namespace) { 02682 iks_insert_attrib(invite, "to", user); 02683 iks_insert_attrib(invite, "id", client->mid); 02684 ast_aji_increment_mid(client->mid); 02685 iks_insert_cdata(body, message, 0); 02686 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference"); 02687 iks_insert_attrib(namespace, "jid", room); 02688 iks_insert_node(invite, body); 02689 iks_insert_node(invite, namespace); 02690 res = ast_aji_send(client, invite); 02691 } else { 02692 ast_log(LOG_ERROR, "Out of memory.\n"); 02693 } 02694 02695 iks_delete(body); 02696 iks_delete(namespace); 02697 iks_delete(invite); 02698 02699 return res; 02700 }
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 2649 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_join_exec().
02650 { 02651 return aji_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nick, NULL); 02652 }
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 2661 of file res_jabber.c.
References aji_set_group_presence().
Referenced by aji_leave_exec().
02662 { 02663 return aji_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nick, NULL); 02664 }
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 1435 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().
01436 { 01437 return aji_send_raw(client, iks_string(iks_stack(x), x)); 01438 }
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 2557 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_send_exec(), aji_test(), gtalk_sendtext(), jingle_sendtext(), and manager_jabber_send().
02558 { 02559 return aji_send_raw_chat(client, 0, NULL, address, message); 02560 }
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 2571 of file res_jabber.c.
References aji_send_raw_chat().
Referenced by aji_sendgroup_exec().
02571 { 02572 return aji_send_raw_chat(client, 1, nick, address, message); 02573 }
static int delete_old_messages | ( | struct aji_client * | client, | |
char * | from | |||
) | [static] |
Definition at line 928 of file res_jabber.c.
References aji_message_destroy(), aji_message::arrived, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_tvdiff_sec(), ast_tvnow(), aji_message::from, aji_message::list, LOG_ERROR, aji_client::message_timeout, and aji_client::messages.
Referenced by aji_handle_message(), and delete_old_messages_all().
00929 { 00930 int deleted = 0; 00931 int isold = 0; 00932 struct aji_message *tmp = NULL; 00933 if (!client) { 00934 ast_log(LOG_ERROR, "Cannot find our XMPP client\n"); 00935 return -1; 00936 } 00937 00938 /* remove old messages */ 00939 AST_LIST_LOCK(&client->messages); 00940 if (AST_LIST_EMPTY(&client->messages)) { 00941 AST_LIST_UNLOCK(&client->messages); 00942 return 0; 00943 } 00944 00945 AST_LIST_TRAVERSE_SAFE_BEGIN(&client->messages, tmp, list) { 00946 if (isold) { 00947 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00948 AST_LIST_REMOVE_CURRENT(list); 00949 aji_message_destroy(tmp); 00950 deleted ++; 00951 } 00952 } else if (ast_tvdiff_sec(ast_tvnow(), tmp->arrived) >= client->message_timeout) { 00953 isold = 1; 00954 if (!from || !strncasecmp(from, tmp->from, strlen(from))) { 00955 AST_LIST_REMOVE_CURRENT(list); 00956 aji_message_destroy(tmp); 00957 deleted ++; 00958 } 00959 } 00960 } 00961 AST_LIST_TRAVERSE_SAFE_END; 00962 AST_LIST_UNLOCK(&client->messages); 00963 00964 return deleted; 00965 }
static int delete_old_messages_all | ( | struct aji_client * | client | ) | [static] |
Definition at line 975 of file res_jabber.c.
References delete_old_messages().
Referenced by aji_recv_loop().
00976 { 00977 return delete_old_messages(client, NULL); 00978 }
static int gtalk_yuck | ( | iks * | node | ) | [static] |
Definition at line 569 of file res_jabber.c.
References ast_debug.
Referenced by aji_handle_presence().
00570 { 00571 if (iks_find_with_attrib(node, "c", "node", "http://www.google.com/xmpp/client/caps")) { 00572 ast_debug(1, "Found resource with Googletalk voice capabilities\n"); 00573 return 1; 00574 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) { 00575 ast_debug(1, "Found resource with Gmail voice/video chat capabilities\n"); 00576 return 1; 00577 } else if (iks_find_with_attrib(node, "caps:c", "ext", "pmuc-v1 sms-v1 video-v1 voice-v1")) { 00578 ast_debug(1, "Found resource with Gmail voice/video chat capabilities (no camera)\n"); 00579 return 1; 00580 } 00581 00582 return 0; 00583 }
static iks * jabber_make_auth | ( | iksid * | id, | |
const char * | pass, | |||
const char * | sid | |||
) | [static] |
Definition at line 593 of file res_jabber.c.
References ast_sha1_hash().
Referenced by aji_act_hook().
00594 { 00595 iks *x, *y; 00596 x = iks_new("iq"); 00597 iks_insert_attrib(x, "type", "set"); 00598 y = iks_insert(x, "query"); 00599 iks_insert_attrib(y, "xmlns", IKS_NS_AUTH); 00600 iks_insert_cdata(iks_insert(y, "username"), id->user, 0); 00601 iks_insert_cdata(iks_insert(y, "resource"), id->resource, 0); 00602 if (sid) { 00603 char buf[41]; 00604 char sidpass[100]; 00605 snprintf(sidpass, sizeof(sidpass), "%s%s", sid, pass); 00606 ast_sha1_hash(buf, sidpass); 00607 iks_insert_cdata(iks_insert(y, "digest"), buf, 0); 00608 } else { 00609 iks_insert_cdata(iks_insert(y, "password"), pass, 0); 00610 } 00611 return x; 00612 }
static int load_module | ( | void | ) | [static] |
Definition at line 4716 of file res_jabber.c.
References aji_cli, aji_join_exec(), aji_leave_exec(), aji_reload(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), ARRAY_LEN, ast_cli_register_multiple(), ast_cond_init, ast_custom_function_register, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, ast_mutex_init, ast_register_application_xml, ASTOBJ_CONTAINER_INIT, clients, EVENT_FLAG_SYSTEM, jabberreceive_function, jabberstatus_function, manager_jabber_send(), and messagelock.
04717 { 04718 ASTOBJ_CONTAINER_INIT(&clients); 04719 if (!aji_reload(0)) 04720 return AST_MODULE_LOAD_DECLINE; 04721 ast_manager_register_xml("JabberSend", EVENT_FLAG_SYSTEM, manager_jabber_send); 04722 ast_register_application_xml(app_ajisend, aji_send_exec); 04723 ast_register_application_xml(app_ajisendgroup, aji_sendgroup_exec); 04724 ast_register_application_xml(app_ajistatus, aji_status_exec); 04725 ast_register_application_xml(app_ajijoin, aji_join_exec); 04726 ast_register_application_xml(app_ajileave, aji_leave_exec); 04727 ast_cli_register_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04728 ast_custom_function_register(&jabberstatus_function); 04729 ast_custom_function_register(&jabberreceive_function); 04730 04731 ast_mutex_init(&messagelock); 04732 ast_cond_init(&message_received_condition, NULL); 04733 return 0; 04734 }
static int manager_jabber_send | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4597 of file res_jabber.c.
References ast_aji_get_client(), ast_aji_send_chat(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by load_module().
04598 { 04599 struct aji_client *client = NULL; 04600 const char *id = astman_get_header(m, "ActionID"); 04601 const char *jabber = astman_get_header(m, "Jabber"); 04602 const char *screenname = astman_get_header(m, "ScreenName"); 04603 const char *message = astman_get_header(m, "Message"); 04604 04605 if (ast_strlen_zero(jabber)) { 04606 astman_send_error(s, m, "No transport specified"); 04607 return 0; 04608 } 04609 if (ast_strlen_zero(screenname)) { 04610 astman_send_error(s, m, "No ScreenName specified"); 04611 return 0; 04612 } 04613 if (ast_strlen_zero(message)) { 04614 astman_send_error(s, m, "No Message specified"); 04615 return 0; 04616 } 04617 04618 astman_send_ack(s, m, "Attempting to send Jabber Message"); 04619 client = ast_aji_get_client(jabber); 04620 if (!client) { 04621 astman_send_error(s, m, "Could not find Sender"); 04622 return 0; 04623 } 04624 if (strchr(screenname, '@') && message) { 04625 ast_aji_send_chat(client, screenname, message); 04626 astman_append(s, "Response: Success\r\n"); 04627 } else { 04628 astman_append(s, "Response: Error\r\n"); 04629 } 04630 if (!ast_strlen_zero(id)) { 04631 astman_append(s, "ActionID: %s\r\n", id); 04632 } 04633 astman_append(s, "\r\n"); 04634 return 0; 04635 }
static int reload | ( | void | ) | [static] |
Definition at line 4740 of file res_jabber.c.
References aji_reload().
04741 { 04742 aji_reload(1); 04743 return 0; 04744 }
static int unload_module | ( | void | ) | [static] |
Definition at line 4675 of file res_jabber.c.
References aji_cli, aji_client_destroy(), AJI_DISCONNECTING, ARRAY_LEN, ast_aji_disconnect(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_custom_function_unregister(), ast_debug, ast_event_unsubscribe(), ast_manager_unregister(), ast_mutex_destroy, ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, clients, device_state_sub, jabberreceive_function, jabberstatus_function, messagelock, and mwi_sub.
04676 { 04677 04678 ast_cli_unregister_multiple(aji_cli, ARRAY_LEN(aji_cli)); 04679 ast_unregister_application(app_ajisend); 04680 ast_unregister_application(app_ajisendgroup); 04681 ast_unregister_application(app_ajistatus); 04682 ast_unregister_application(app_ajijoin); 04683 ast_unregister_application(app_ajileave); 04684 ast_manager_unregister("JabberSend"); 04685 ast_custom_function_unregister(&jabberstatus_function); 04686 if (mwi_sub) { 04687 ast_event_unsubscribe(mwi_sub); 04688 } 04689 if (device_state_sub) { 04690 ast_event_unsubscribe(device_state_sub); 04691 } 04692 ast_custom_function_unregister(&jabberreceive_function); 04693 04694 ASTOBJ_CONTAINER_TRAVERSE(&clients, 1, { 04695 ASTOBJ_WRLOCK(iterator); 04696 ast_debug(3, "JABBER: Releasing and disconnecting client: %s\n", iterator->name); 04697 iterator->state = AJI_DISCONNECTING; 04698 ASTOBJ_UNLOCK(iterator); 04699 pthread_join(iterator->thread, NULL); 04700 ast_aji_disconnect(iterator); 04701 }); 04702 04703 ASTOBJ_CONTAINER_DESTROYALL(&clients, aji_client_destroy); 04704 ASTOBJ_CONTAINER_DESTROY(&clients); 04705 04706 ast_cond_destroy(&message_received_condition); 04707 ast_mutex_destroy(&messagelock); 04708 04709 return 0; 04710 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 4751 of file res_jabber.c.
struct ast_cli_entry aji_cli[] [static] |
char* app_ajijoin = "JabberJoin" [static] |
Definition at line 392 of file res_jabber.c.
char* app_ajileave = "JabberLeave" [static] |
Definition at line 393 of file res_jabber.c.
char* app_ajisend = "JabberSend" [static] |
Definition at line 389 of file res_jabber.c.
char* app_ajisendgroup = "JabberSendGroup" [static] |
Definition at line 390 of file res_jabber.c.
char* app_ajistatus = "JabberStatus" [static] |
Definition at line 391 of file res_jabber.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 4751 of file res_jabber.c.
struct aji_capabilities* capabilities = NULL [static] |
struct aji_client_container clients [static] |
Definition at line 395 of file res_jabber.c.
Referenced by aji_cli_create_collection(), aji_cli_create_leafnode(), aji_cli_delete_pubsub_node(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_create_client(), aji_do_set_debug(), aji_reload(), aji_show_buddies(), aji_show_clients(), aji_test(), ast_aji_get_client(), ast_aji_get_clients(), gtalk_load_config(), jingle_load_config(), load_module(), and unload_module().
struct ast_event_sub* device_state_sub = NULL [static] |
Definition at line 398 of file res_jabber.c.
struct ast_flags globalflags = { AJI_AUTOREGISTER | AJI_AUTOACCEPT } [static] |
struct ast_custom_function jabberreceive_function [static] |
Initial value:
{ .name = "JABBER_RECEIVE", .read = acf_jabberreceive_read, }
Definition at line 914 of file res_jabber.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function jabberstatus_function [static] |
Initial value:
{ .name = "JABBER_STATUS", .read = acf_jabberstatus_read, }
Definition at line 750 of file res_jabber.c.
Referenced by load_module(), and unload_module().
ast_cond_t message_received_condition [static] |
Definition at line 399 of file res_jabber.c.
ast_mutex_t messagelock [static] |
Definition at line 400 of file res_jabber.c.
Referenced by acf_jabberreceive_read(), aji_handle_message(), load_module(), and unload_module().
struct ast_event_sub* mwi_sub = NULL [static] |
Definition at line 397 of file res_jabber.c.
Referenced by aji_init_event_distribution(), handle_subscribe(), handle_unsubscribe(), mwi_sub_destroy(), poll_subscribed_mailbox(), poll_subscribed_mailboxes(), and unload_module().
struct ast_flags pubsubflags = { 0 } [static] |
PubSub flags, initialized to default values.
Definition at line 406 of file res_jabber.c.
Referenced by aji_cli_purge_pubsub_nodes(), aji_create_client(), aji_handle_pubsub_error(), and aji_publish_device_state().