Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Enumerations | Functions | Variables
res_xmpp.c File Reference

XMPP client and component module. More...

#include "asterisk.h"
#include <ctype.h>
#include <iksemel.h>
#include "asterisk/xmpp.h"
#include "asterisk/module.h"
#include "asterisk/manager.h"
#include "asterisk/app.h"
#include "asterisk/mwi.h"
#include "asterisk/message.h"
#include "asterisk/cli.h"
#include "asterisk/config_options.h"
#include "asterisk/json.h"
Include dependency graph for res_xmpp.c:

Go to the source code of this file.

Data Structures

struct  ast_xmpp_client_config
 XMPP Client Configuration. More...
 
struct  ast_xmpp_global_config
 XMPP Global Configuration. More...
 
struct  xmpp_config
 
struct  xmpp_pak_handler
 Defined handlers for different PAK types. More...
 
struct  xmpp_state_handler
 Defined handlers for XMPP client states. More...
 

Macros

#define BUDDY_BUCKETS   53
 Number of buckets for buddies (per client) More...
 
#define BUDDY_NOT_IN_ROSTER   7
 
#define BUDDY_OFFLINE   6
 
#define CLIENT_BUCKETS   53
 Number of buckets for client connections. More...
 
#define RESOURCE_BUCKETS   53
 Number of buckets for resources (per buddy) More...
 
#define STATUS_DISAPPEAR   6
 Status for a disappearing buddy. More...
 
#define XMPP_TLS_NS   "urn:ietf:params:xml:ns:xmpp-tls"
 Namespace for TLS support. More...
 

Enumerations

enum  {
  XMPP_AUTOPRUNE = (1 << 0) , XMPP_AUTOREGISTER = (1 << 1) , XMPP_AUTOACCEPT = (1 << 2) , XMPP_DEBUG = (1 << 3) ,
  XMPP_USETLS = (1 << 4) , XMPP_USESASL = (1 << 5) , XMPP_FORCESSL = (1 << 6) , XMPP_KEEPALIVE = (1 << 7) ,
  XMPP_COMPONENT = (1 << 8) , XMPP_SEND_TO_DIALPLAN = (1 << 9) , XMPP_DISTRIBUTE_EVENTS = (1 << 10)
}
 Supported general configuration flags. More...
 
enum  { XMPP_XEP0248 = (1 << 0) , XMPP_PUBSUB = (1 << 1) , XMPP_PUBSUB_AUTOCREATE = (1 << 2) }
 Supported pubsub configuration flags. More...
 

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 AO2_GLOBAL_OBJ_STATIC (globals)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_xmpp_chatroom_invite (struct ast_xmpp_client *client, const char *user, const char *room, const char *message)
 Invite a user to an XMPP multi-user chatroom. More...
 
int ast_xmpp_chatroom_join (struct ast_xmpp_client *client, const char *room, const char *nickname)
 Join an XMPP multi-user chatroom. More...
 
int ast_xmpp_chatroom_leave (struct ast_xmpp_client *client, const char *room, const char *nickname)
 Leave an XMPP multi-user chatroom. More...
 
int ast_xmpp_chatroom_send (struct ast_xmpp_client *client, const char *nickname, const char *address, const char *message)
 Send a message to an XMPP multi-user chatroom. More...
 
static void * ast_xmpp_client_config_alloc (const char *cat)
 Allocator function for configuration. More...
 
static void ast_xmpp_client_config_destructor (void *obj)
 Destructor function for configuration. More...
 
int ast_xmpp_client_disconnect (struct ast_xmpp_client *client)
 Disconnect an XMPP client connection. More...
 
struct ast_xmpp_clientast_xmpp_client_find (const char *name)
 Find an XMPP client connection using a given name. More...
 
void ast_xmpp_client_lock (struct ast_xmpp_client *client)
 Lock an XMPP client connection. More...
 
int ast_xmpp_client_send (struct ast_xmpp_client *client, iks *stanza)
 Send an XML stanza out using an established XMPP client connection. More...
 
int ast_xmpp_client_send_message (struct ast_xmpp_client *client, const char *user, const char *message)
 Send a message to a given user using an established XMPP client connection. More...
 
void ast_xmpp_client_unlock (struct ast_xmpp_client *client)
 Unlock an XMPP client connection. More...
 
void ast_xmpp_client_unref (struct ast_xmpp_client *client)
 Release XMPP client connection reference. More...
 
void ast_xmpp_increment_mid (char *mid)
 Helper function which increments the message identifier. More...
 
static int cached_devstate_cb (void *obj, void *arg, int flags)
 
static int client_bitfield_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int client_buddy_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int client_status_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
 CONFIG_INFO_STANDARD (cfg_info, globals, xmpp_config_alloc,.files=ACO_FILES(&res_xmpp_conf),.post_apply_config=xmpp_config_post_apply,)
 
static int delete_old_messages (struct ast_xmpp_client *client, char *from)
 
static int fetch_access_token (struct ast_xmpp_client_config *cfg)
 
static int get_buddy_status (struct ast_xmpp_client_config *clientcfg, char *screenname, char *resource)
 
static int global_bitfield_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 
static int load_module (void)
 Load the module. More...
 
static int manager_jabber_send (struct mansession *s, const struct message *m)
 
static int reload (void)
 
static void sleep_with_backoff (unsigned int *sleep_time)
 
static int unload_module (void)
 
static int xmpp_action_hook (void *data, int type, iks *node)
 Action hook for when things occur. More...
 
static int xmpp_buddy_cmp (void *obj, void *arg, int flags)
 Comparator function for XMPP buddy. More...
 
static void xmpp_buddy_destructor (void *obj)
 Destructor callback function for XMPP buddy. More...
 
static int xmpp_buddy_hash (const void *obj, const int flags)
 Hashing function for XMPP buddy. More...
 
static char * xmpp_cli_create_collection (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Method to expose PubSub collection node creation via CLI. More...
 
static char * xmpp_cli_create_leafnode (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Method to expose PubSub leaf node creation via CLI. More...
 
static char * xmpp_cli_delete_pubsub_node (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Method to expose PubSub node deletion via CLI. More...
 
static char * xmpp_cli_list_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Method to expose PubSub node list via CLI. More...
 
static char * xmpp_cli_purge_pubsub_nodes (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Method to purge PubSub nodes via CLI. More...
 
static struct ast_xmpp_clientxmpp_client_alloc (const char *name)
 Allocator function for ast_xmpp_client. More...
 
static int xmpp_client_authenticate (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we need to authenticate. More...
 
static int xmpp_client_authenticate_digest (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we need to authenticate using non-SASL. More...
 
static int xmpp_client_authenticate_sasl (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we need to authenticate using SASL. More...
 
static int xmpp_client_authenticating (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we are authenticating. More...
 
static void xmpp_client_change_state (struct ast_xmpp_client *client, int state)
 Internal function which changes the XMPP client state. More...
 
static int xmpp_client_config_merge_buddies (void *obj, void *arg, int flags)
 
static int xmpp_client_config_post_apply (void *obj, void *arg, int flags)
 
static struct ast_xmpp_buddyxmpp_client_create_buddy (struct ao2_container *container, const char *id)
 Internal function which creates a buddy on a client. More...
 
static void xmpp_client_destructor (void *obj)
 Destructor callback function for XMPP client. More...
 
static void * xmpp_client_find_or_create (const char *category)
 Look up existing client or create a new one. More...
 
static int xmpp_client_receive (struct ast_xmpp_client *client, unsigned int timeout)
 Internal function which receives data from the XMPP client connection. More...
 
static int xmpp_client_reconnect (struct ast_xmpp_client *client)
 Internal function used to reconnect an XMPP client to its server. More...
 
static int xmpp_client_request_tls (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we need to request TLS support. More...
 
static int xmpp_client_requested_tls (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we receive a response to our TLS initiation request. More...
 
static int xmpp_client_send_disco_info_request (struct ast_xmpp_client *client, const char *to, const char *from)
 Helper function which sends a discovery information request to a user. More...
 
static int xmpp_client_send_message (struct ast_xmpp_client *client, int group, const char *nick, const char *address, const char *message)
 Internal function used to send a message to a user or chatroom. More...
 
static int xmpp_client_send_raw_message (struct ast_xmpp_client *client, const char *message)
 Internal function which sends a raw message. More...
 
static int xmpp_client_service_discovery_get_hook (void *data, ikspak *pak)
 Hook function called when client receives a service discovery get message. More...
 
static int xmpp_client_service_discovery_result_hook (void *data, ikspak *pak)
 Hook function called when client receives a service discovery result message. More...
 
static int xmpp_client_set_group_presence (struct ast_xmpp_client *client, const char *room, int level, const char *nick)
 
static void xmpp_client_set_presence (struct ast_xmpp_client *client, const char *to, const char *from, int level, const char *desc)
 Internal function which changes the presence status of an XMPP client. More...
 
static int xmpp_client_subscribe_user (void *obj, void *arg, int flags)
 Callback function which subscribes to a user if needed. More...
 
static void * xmpp_client_thread (void *data)
 XMPP client connection thread. More...
 
static int xmpp_client_unsubscribe_user (struct ast_xmpp_client *client, const char *user)
 Helper function which unsubscribes a user and removes them from the roster. More...
 
static int xmpp_component_authenticate (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we should authenticate as a component. More...
 
static int xmpp_component_authenticating (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
 Internal function called when we authenticated as a component. More...
 
static int xmpp_component_register_get_hook (void *data, ikspak *pak)
 Hook function called when the component is queried about registration. More...
 
static int xmpp_component_register_set_hook (void *data, ikspak *pak)
 Hook function called when someone registers to the component. More...
 
static int xmpp_component_service_discovery_get_hook (void *data, ikspak *pak)
 Hook function called when component receives a service discovery get message. More...
 
static int xmpp_component_service_discovery_items_hook (void *data, ikspak *pak)
 Hook function called when we receive a service discovery items request. More...
 
static void * xmpp_config_alloc (void)
 Allocator for XMPP configuration. More...
 
static int xmpp_config_cmp (void *obj, void *arg, int flags)
 Comparator function for configuration. More...
 
static void xmpp_config_destructor (void *obj)
 Destructor for XMPP configuration. More...
 
static void * xmpp_config_find (struct ao2_container *tmp_container, const char *category)
 Find function for configuration. More...
 
static void xmpp_config_post_apply (void)
 
static int xmpp_config_prelink (void *newitem)
 
static int xmpp_connect_hook (void *data, ikspak *pak)
 Hook function called when client finishes authenticating with the server. More...
 
static char * xmpp_do_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void xmpp_init_event_distribution (struct ast_xmpp_client *client)
 Initialize collections for event distribution. More...
 
static int xmpp_io_recv (struct ast_xmpp_client *client, char *buffer, size_t buf_len, int timeout)
 Internal function which polls on an XMPP client and receives data. More...
 
static int xmpp_is_secure (struct ast_xmpp_client *client)
 Helper function which returns whether an XMPP client connection is secure or not. More...
 
static int xmpp_join_exec (struct ast_channel *chan, const char *data)
 Application to join a chat room. More...
 
static int xmpp_leave_exec (struct ast_channel *chan, const char *data)
 Application to leave a chat room. More...
 
static void xmpp_log_hook (void *data, const char *xmpp, size_t size, int incoming)
 Logging hook function. More...
 
static void xmpp_message_destroy (struct ast_xmpp_message *message)
 Destroy function for XMPP messages. More...
 
static int xmpp_pak_message (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
 Internal function called when a message is received. More...
 
static int xmpp_pak_presence (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
 Internal function called when a presence message is received. More...
 
static int xmpp_pak_s10n (struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
 Internal function called when a subscription message is received. More...
 
static int xmpp_ping_request (struct ast_xmpp_client *client, const char *to, const char *from)
 Helper function which sends a ping request to a server. More...
 
static iks * xmpp_pubsub_build_node_config (iks *pubsub, const char *node_type, const char *collection_name)
 
static iks * xmpp_pubsub_build_node_request (struct ast_xmpp_client *client, const char *collection)
 Build the a node request. More...
 
static iks * xmpp_pubsub_build_publish_skeleton (struct ast_xmpp_client *client, const char *node, const char *event_type, unsigned int cachable)
 Build the skeleton of a publish. More...
 
static void xmpp_pubsub_create_affiliations (struct ast_xmpp_client *client, const char *node)
 Add Owner affiliations for pubsub node. More...
 
static void xmpp_pubsub_create_collection (struct ast_xmpp_client *client, const char *collection_name)
 Create a PubSub collection node. More...
 
static void xmpp_pubsub_create_leaf (struct ast_xmpp_client *client, const char *collection_name, const char *leaf_name)
 Create a PubSub leaf node. More...
 
static void xmpp_pubsub_create_node (struct ast_xmpp_client *client, const char *node_type, const char *name, const char *collection_name)
 Create a pubsub node. More...
 
static void xmpp_pubsub_delete_node (struct ast_xmpp_client *client, const char *node_name)
 Delete a PubSub node. More...
 
static int xmpp_pubsub_delete_node_list (void *data, ikspak *pak)
 Delete pubsub item lists. More...
 
static void xmpp_pubsub_devstate_cb (void *data, struct stasis_subscription *sub, struct stasis_message *msg)
 Callback function for device state events. More...
 
static int xmpp_pubsub_handle_error (void *data, ikspak *pak)
 
static int xmpp_pubsub_handle_event (void *data, ikspak *pak)
 Callback for handling PubSub events. More...
 
static iks * xmpp_pubsub_iq_create (struct ast_xmpp_client *client, const char *type)
 Create an IQ packet. More...
 
static void xmpp_pubsub_mwi_cb (void *data, struct stasis_subscription *sub, struct stasis_message *msg)
 Callback function for MWI events. More...
 
static void xmpp_pubsub_publish_device_state (struct ast_xmpp_client *client, const char *device, const char *device_state, unsigned int cachable)
 Publish device state to a PubSub node. More...
 
static void xmpp_pubsub_publish_mwi (struct ast_xmpp_client *client, const char *mailbox, const char *oldmsgs, const char *newmsgs)
 Publish MWI to a PubSub node. More...
 
static void xmpp_pubsub_purge_nodes (struct ast_xmpp_client *client, const char *collection_name)
 
static int xmpp_pubsub_receive_node_list (void *data, ikspak *pak)
 Receive pubsub item lists. More...
 
static void xmpp_pubsub_request_nodes (struct ast_xmpp_client *client, const char *collection)
 Request item list from pubsub. More...
 
static void xmpp_pubsub_subscribe (struct ast_xmpp_client *client, const char *node)
 Subscribe to a PubSub node. More...
 
static void xmpp_pubsub_unsubscribe (struct ast_xmpp_client *client, const char *node)
 Unsubscribe from a PubSub node. More...
 
static int xmpp_resource_cmp (void *obj, void *arg, int flags)
 Comparator function for XMPP resource. More...
 
static void xmpp_resource_destructor (void *obj)
 Destructor callback function for XMPP resource. More...
 
static int xmpp_resource_hash (const void *obj, const int flags)
 Hashing function for XMPP resource. More...
 
static int xmpp_resource_immediate (void *obj, void *arg, int flags)
 Internal astobj2 callback function which returns the first resource, which is the highest priority one. More...
 
static int xmpp_resource_is_available (void *obj, void *arg, int flags)
 Callback function which returns when the resource is available. More...
 
static int xmpp_roster_hook (void *data, ikspak *pak)
 Hook function called when roster is received from server. More...
 
static int xmpp_send_cb (const struct ast_msg *msg, const char *to, const char *from)
 
static int xmpp_send_exec (struct ast_channel *chan, const char *data)
 
static int xmpp_send_stream_header (struct ast_xmpp_client *client, const struct ast_xmpp_client_config *cfg, const char *to)
 Helper function which sends an XMPP stream header to the server. More...
 
static int xmpp_sendgroup_exec (struct ast_channel *chan, const char *data)
 Application to send a message to a groupchat. More...
 
static char * xmpp_show_buddies (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * xmpp_show_clients (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk XMPP 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
 
static const char * app_ajijoin = "JabberJoin"
 
static const char * app_ajileave = "JabberLeave"
 
static const char * app_ajisend = "JabberSend"
 
static const char * app_ajisendgroup = "JabberSendGroup"
 
static const char * app_ajistatus = "JabberStatus"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct aco_type client_option
 
struct aco_typeclient_options [] = ACO_TYPES(&client_option)
 
static int debug
 Global debug status. More...
 
static struct aco_type global_option
 
struct aco_typeglobal_options [] = ACO_TYPES(&global_option)
 
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 const struct ast_msg_tech msg_tech
 
struct aco_file res_xmpp_conf
 
static struct ast_cli_entry xmpp_cli []
 
static const struct xmpp_pak_handler xmpp_pak_handlers []
 
static const struct xmpp_state_handler xmpp_state_handlers []
 

Detailed Description

XMPP client and component module.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Iksemel http://code.google.com/p/iksemel/

A reference module for interfacting Asterisk directly as a client or component with an XMPP/Jabber compliant server.

This module is based upon the original res_jabber as done by Matt O'Gorman.

Definition in file res_xmpp.c.

Macro Definition Documentation

◆ BUDDY_BUCKETS

#define BUDDY_BUCKETS   53

Number of buckets for buddies (per client)

Definition at line 429 of file res_xmpp.c.

◆ BUDDY_NOT_IN_ROSTER

#define BUDDY_NOT_IN_ROSTER   7

Definition at line 1628 of file res_xmpp.c.

◆ BUDDY_OFFLINE

#define BUDDY_OFFLINE   6

Definition at line 1627 of file res_xmpp.c.

◆ CLIENT_BUCKETS

#define CLIENT_BUCKETS   53

Number of buckets for client connections.

Definition at line 426 of file res_xmpp.c.

◆ RESOURCE_BUCKETS

#define RESOURCE_BUCKETS   53

Number of buckets for resources (per buddy)

Definition at line 432 of file res_xmpp.c.

◆ STATUS_DISAPPEAR

#define STATUS_DISAPPEAR   6

Status for a disappearing buddy.

Definition at line 438 of file res_xmpp.c.

◆ XMPP_TLS_NS

#define XMPP_TLS_NS   "urn:ietf:params:xml:ns:xmpp-tls"

Namespace for TLS support.

Definition at line 435 of file res_xmpp.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Supported general configuration flags.

Enumerator
XMPP_AUTOPRUNE 
XMPP_AUTOREGISTER 
XMPP_AUTOACCEPT 
XMPP_DEBUG 
XMPP_USETLS 
XMPP_USESASL 
XMPP_FORCESSL 
XMPP_KEEPALIVE 
XMPP_COMPONENT 
XMPP_SEND_TO_DIALPLAN 
XMPP_DISTRIBUTE_EVENTS 

Definition at line 404 of file res_xmpp.c.

404 {
405 XMPP_AUTOPRUNE = (1 << 0),
406 XMPP_AUTOREGISTER = (1 << 1),
407 XMPP_AUTOACCEPT = (1 << 2),
408 XMPP_DEBUG = (1 << 3),
409 XMPP_USETLS = (1 << 4),
410 XMPP_USESASL = (1 << 5),
411 XMPP_FORCESSL = (1 << 6),
412 XMPP_KEEPALIVE = (1 << 7),
413 XMPP_COMPONENT = (1 << 8),
414 XMPP_SEND_TO_DIALPLAN = (1 << 9),
415 XMPP_DISTRIBUTE_EVENTS = (1 << 10),
416};
@ XMPP_AUTOREGISTER
Definition: res_xmpp.c:406
@ XMPP_DISTRIBUTE_EVENTS
Definition: res_xmpp.c:415
@ XMPP_USETLS
Definition: res_xmpp.c:409
@ XMPP_AUTOPRUNE
Definition: res_xmpp.c:405
@ XMPP_FORCESSL
Definition: res_xmpp.c:411
@ XMPP_USESASL
Definition: res_xmpp.c:410
@ XMPP_AUTOACCEPT
Definition: res_xmpp.c:407
@ XMPP_DEBUG
Definition: res_xmpp.c:408
@ XMPP_KEEPALIVE
Definition: res_xmpp.c:412
@ XMPP_COMPONENT
Definition: res_xmpp.c:413
@ XMPP_SEND_TO_DIALPLAN
Definition: res_xmpp.c:414

◆ anonymous enum

anonymous enum

Supported pubsub configuration flags.

Enumerator
XMPP_XEP0248 
XMPP_PUBSUB 
XMPP_PUBSUB_AUTOCREATE 

Definition at line 419 of file res_xmpp.c.

419 {
420 XMPP_XEP0248 = (1 << 0),
421 XMPP_PUBSUB = (1 << 1),
422 XMPP_PUBSUB_AUTOCREATE = (1 << 2),
423};
@ XMPP_XEP0248
Definition: res_xmpp.c:420
@ XMPP_PUBSUB
Definition: res_xmpp.c:421
@ XMPP_PUBSUB_AUTOCREATE
Definition: res_xmpp.c:422

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4703 of file res_xmpp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4703 of file res_xmpp.c.

◆ acf_jabberreceive_read()

static int acf_jabberreceive_read ( struct ast_channel chan,
const char *  name,
char *  data,
char *  buf,
size_t  buflen 
)
static

Definition at line 1933 of file res_xmpp.c.

1934{
1936 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1937 char *parse = NULL;
1938 int timeout, jidlen, resourcelen, found = 0;
1939 struct timeval start;
1940 long diff = 0;
1941 struct ast_xmpp_message *message;
1943 AST_APP_ARG(account);
1944 AST_APP_ARG(jid);
1945 AST_APP_ARG(timeout);
1946 );
1948 AST_APP_ARG(screenname);
1949 AST_APP_ARG(resource);
1950 );
1951
1952 if (ast_strlen_zero(data)) {
1953 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
1954 return -1;
1955 }
1956
1957 parse = ast_strdupa(data);
1959
1960 if (args.argc < 2 || args.argc > 3) {
1961 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
1962 return -1;
1963 }
1964
1965 parse = ast_strdupa(args.jid);
1966 AST_NONSTANDARD_APP_ARGS(jid, parse, '/');
1967 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > XMPP_MAX_JIDLEN) {
1968 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse);
1969 return -1;
1970 }
1971
1972 if (ast_strlen_zero(args.timeout)) {
1973 timeout = 20;
1974 } else {
1975 sscanf(args.timeout, "%d", &timeout);
1976 if (timeout <= 0) {
1977 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
1978 return -1;
1979 }
1980 }
1981
1982 jidlen = strlen(jid.screenname);
1983 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource);
1984
1985 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.account))) {
1986 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account);
1987 return -1;
1988 }
1989
1990 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid);
1991
1992 start = ast_tvnow();
1993
1994 if (chan && ast_autoservice_start(chan) < 0) {
1995 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", ast_channel_name(chan));
1996 return -1;
1997 }
1998
1999 /* search the messages list, grab the first message that matches with
2000 * the from JID we're expecting, and remove it from the messages list */
2001 while (diff < timeout) {
2002 struct timespec ts = { 0, };
2003 struct timeval wait;
2004 int res = 0;
2005
2006 wait = ast_tvadd(start, ast_tv(timeout, 0));
2007 ts.tv_sec = wait.tv_sec;
2008 ts.tv_nsec = wait.tv_usec * 1000;
2009
2010 /* wait up to timeout seconds for an incoming message */
2012 if (AST_LIST_EMPTY(&clientcfg->client->messages)) {
2014 }
2016 if (res == ETIMEDOUT) {
2017 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout);
2018 break;
2019 }
2020
2021 AST_LIST_LOCK(&clientcfg->client->messages);
2022 AST_LIST_TRAVERSE_SAFE_BEGIN(&clientcfg->client->messages, message, list) {
2023 if (jid.argc == 1) {
2024 /* no resource provided, compare bare JIDs */
2025 if (strncasecmp(jid.screenname, message->from, jidlen)) {
2026 continue;
2027 }
2028 } else {
2029 /* resource appended, compare bare JIDs and resources */
2030 char *resource = strchr(message->from, '/');
2031 if (!resource || strlen(resource) == 0) {
2032 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", message->from);
2033 if (strncasecmp(jid.screenname, message->from, jidlen)) {
2034 continue;
2035 }
2036 } else {
2037 resource ++;
2038 if (strncasecmp(jid.screenname, message->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) {
2039 continue;
2040 }
2041 }
2042 }
2043 /* check if the message is not too old */
2044 if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= clientcfg->message_timeout) {
2045 ast_debug(3, "Found old message from %s, deleting it\n", message->from);
2048 continue;
2049 }
2050 found = 1;
2051 ast_copy_string(buf, message->message, buflen);
2054 break;
2055 }
2057 AST_LIST_UNLOCK(&clientcfg->client->messages);
2058 if (found) {
2059 break;
2060 }
2061
2062 /* check timeout */
2063 diff = ast_tvdiff_ms(ast_tvnow(), start);
2064 }
2065
2066 if (chan && ast_autoservice_stop(chan) < 0) {
2067 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", ast_channel_name(chan));
2068 }
2069
2070 /* return if we timed out */
2071 if (!found) {
2072 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid);
2073 return -1;
2074 }
2075
2076 return 0;
2077}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
static struct console_pvt globals
const char * ast_channel_name(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_NOTICE
#define LOG_WARNING
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
static ast_mutex_t messagelock
Definition: res_xmpp.c:523
static void * xmpp_config_find(struct ao2_container *tmp_container, const char *category)
Find function for configuration.
Definition: res_xmpp.c:657
static void xmpp_message_destroy(struct ast_xmpp_message *message)
Destroy function for XMPP messages.
Definition: res_xmpp.c:538
static ast_cond_t message_received_condition
Definition: res_xmpp.c:522
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
XMPP Client Configuration.
Definition: res_xmpp.c:450
XMPP Message.
Definition: xmpp.h:101
char * message
Definition: xmpp.h:103
const char * args
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
Definition: time.h:73
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define XMPP_MAX_JIDLEN
Definition: xmpp.h:62

References ao2_cleanup, ao2_global_obj_ref, args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_name(), ast_cond_timedwait, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, 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_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(), buf, globals, LOG_NOTICE, LOG_WARNING, ast_xmpp_message::message, message_received_condition, messagelock, name, NULL, RAII_VAR, xmpp_config_find(), XMPP_MAX_JIDLEN, and xmpp_message_destroy().

◆ acf_jabberstatus_read()

static int acf_jabberstatus_read ( struct ast_channel chan,
const char *  name,
char *  data,
char *  buf,
size_t  buflen 
)
static

Definition at line 1666 of file res_xmpp.c.

1667{
1669 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1671 AST_APP_ARG(sender);
1672 AST_APP_ARG(jid);
1673 );
1675 AST_APP_ARG(screenname);
1676 AST_APP_ARG(resource);
1677 );
1678
1679 if (ast_strlen_zero(data)) {
1680 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n");
1681 return 0;
1682 }
1684
1685 if (args.argc != 2) {
1686 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n");
1687 return -1;
1688 }
1689
1690 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/');
1691 if (jid.argc < 1 || jid.argc > 2) {
1692 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid);
1693 return -1;
1694 }
1695
1696 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1697 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
1698 return -1;
1699 }
1700
1701 snprintf(buf, buflen, "%d", get_buddy_status(clientcfg, jid.screenname, jid.resource));
1702
1703 return 0;
1704}
#define LOG_ERROR
static int get_buddy_status(struct ast_xmpp_client_config *clientcfg, char *screenname, char *resource)
Definition: res_xmpp.c:1630

References ao2_cleanup, ao2_global_obj_ref, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strlen_zero(), buf, get_buddy_status(), globals, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, and xmpp_config_find().

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( globals  )
static

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 4703 of file res_xmpp.c.

◆ ast_xmpp_chatroom_invite()

int ast_xmpp_chatroom_invite ( struct ast_xmpp_client client,
const char *  user,
const char *  room,
const char *  message 
)

Invite a user to an XMPP multi-user chatroom.

Parameters
clientPointer to the client
userJID of the user
roomName of the chatroom
messageMessage to send with the invitation
Return values
0on success
-1on failure

Definition at line 943 of file res_xmpp.c.

944{
945 int res = 0;
946 iks *invite, *body = NULL, *namespace = NULL;
947
948 if (!(invite = iks_new("message")) || !(body = iks_new("body")) || !(namespace = iks_new("x"))) {
949 res = -1;
950 goto done;
951 }
952
953 iks_insert_attrib(invite, "to", user);
954 ast_xmpp_client_lock(client);
955 iks_insert_attrib(invite, "id", client->mid);
958 iks_insert_cdata(body, message, 0);
959 iks_insert_node(invite, body);
960 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
961 iks_insert_attrib(namespace, "jid", room);
962 iks_insert_node(invite, namespace);
963
964 res = ast_xmpp_client_send(client, invite);
965
966done:
967 iks_delete(namespace);
968 iks_delete(body);
969 iks_delete(invite);
970
971 return res;
972}
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
Definition: res_xmpp.c:2534
void ast_xmpp_client_unlock(struct ast_xmpp_client *client)
Unlock an XMPP client connection.
Definition: res_xmpp.c:904
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1025
void ast_xmpp_client_lock(struct ast_xmpp_client *client)
Lock an XMPP client connection.
Definition: res_xmpp.c:899
char mid[6]
Definition: xmpp.h:125
structure to hold users read from users.conf
int done
Definition: test_amihooks.c:48

References ast_xmpp_client_lock(), ast_xmpp_client_send(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), done, ast_xmpp_client::mid, and NULL.

◆ ast_xmpp_chatroom_join()

int ast_xmpp_chatroom_join ( struct ast_xmpp_client client,
const char *  room,
const char *  nickname 
)

Join an XMPP multi-user chatroom.

Parameters
clientPointer to the client
roomName of the chatroom
nicknameNickname to use
Return values
0on success
-1on failure

Definition at line 1010 of file res_xmpp.c.

1011{
1012 return xmpp_client_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nickname);
1013}
static int xmpp_client_set_group_presence(struct ast_xmpp_client *client, const char *room, int level, const char *nick)
Definition: res_xmpp.c:974

References xmpp_client_set_group_presence().

Referenced by xmpp_join_exec().

◆ ast_xmpp_chatroom_leave()

int ast_xmpp_chatroom_leave ( struct ast_xmpp_client client,
const char *  room,
const char *  nickname 
)

Leave an XMPP multi-user chatroom.

Parameters
clientPointer to the client
roomName of the chatroom
nicknameNickname being used
Return values
0on success
-1on failure

Definition at line 1020 of file res_xmpp.c.

1021{
1022 return xmpp_client_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nickname);
1023}

References xmpp_client_set_group_presence().

Referenced by xmpp_leave_exec().

◆ ast_xmpp_chatroom_send()

int ast_xmpp_chatroom_send ( struct ast_xmpp_client client,
const char *  nickname,
const char *  address,
const char *  message 
)

Send a message to an XMPP multi-user chatroom.

Parameters
clientPointer to the client
nicknameNickname to use
addressAddress of the room
messageMessage itself
Return values
0on success
-1on failure

Definition at line 1015 of file res_xmpp.c.

1016{
1017 return xmpp_client_send_message(client, 1, nickname, address, message);
1018}
char * address
Definition: f2c.h:59
static int xmpp_client_send_message(struct ast_xmpp_client *client, int group, const char *nick, const char *address, const char *message)
Internal function used to send a message to a user or chatroom.
Definition: res_xmpp.c:910

References xmpp_client_send_message().

Referenced by xmpp_sendgroup_exec().

◆ ast_xmpp_client_config_alloc()

static void * ast_xmpp_client_config_alloc ( const char *  cat)
static

Allocator function for configuration.

Definition at line 677 of file res_xmpp.c.

678{
679 struct ast_xmpp_client_config *cfg;
680
681 if (!(cfg = ao2_alloc(sizeof(*cfg), ast_xmpp_client_config_destructor))) {
682 return NULL;
683 }
684
685 if (ast_string_field_init(cfg, 512)) {
686 ao2_ref(cfg, -1);
687 return NULL;
688 }
689
690 if (!(cfg->client = xmpp_client_find_or_create(cat))) {
691 ao2_ref(cfg, -1);
692 return NULL;
693 }
694
697 if (!cfg->buddies) {
698 ao2_ref(cfg, -1);
699 return NULL;
700 }
701
702 ast_string_field_set(cfg, name, cat);
703
704 return cfg;
705}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static int xmpp_buddy_cmp(void *obj, void *arg, int flags)
Comparator function for XMPP buddy.
Definition: res_xmpp.c:587
#define BUDDY_BUCKETS
Number of buckets for buddies (per client)
Definition: res_xmpp.c:429
static void * xmpp_client_find_or_create(const char *category)
Look up existing client or create a new one.
Definition: res_xmpp.c:663
static void ast_xmpp_client_config_destructor(void *obj)
Destructor function for configuration.
Definition: res_xmpp.c:529
static int xmpp_buddy_hash(const void *obj, const int flags)
Hashing function for XMPP buddy.
Definition: res_xmpp.c:578
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
struct ao2_container * buddies
Definition: res_xmpp.c:470
struct ast_xmpp_client * client
Definition: res_xmpp.c:469

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, ast_string_field_init, ast_string_field_set, ast_xmpp_client_config_destructor(), ast_xmpp_client_config::buddies, BUDDY_BUCKETS, ast_xmpp_client_config::client, name, NULL, xmpp_buddy_cmp(), xmpp_buddy_hash(), and xmpp_client_find_or_create().

◆ ast_xmpp_client_config_destructor()

static void ast_xmpp_client_config_destructor ( void *  obj)
static

Destructor function for configuration.

Definition at line 529 of file res_xmpp.c.

530{
531 struct ast_xmpp_client_config *cfg = obj;
533 ao2_cleanup(cfg->client);
534 ao2_cleanup(cfg->buddies);
535}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ao2_cleanup, ast_string_field_free_memory, ast_xmpp_client_config::buddies, and ast_xmpp_client_config::client.

Referenced by ast_xmpp_client_config_alloc().

◆ ast_xmpp_client_disconnect()

int ast_xmpp_client_disconnect ( struct ast_xmpp_client client)

Disconnect an XMPP client connection.

Parameters
clientPointer to the client
Return values
0on success
-1on failure

Definition at line 3525 of file res_xmpp.c.

3526{
3527 if ((client->thread != AST_PTHREADT_NULL) && !pthread_equal(pthread_self(), client->thread)) {
3529 pthread_cancel(client->thread);
3530 pthread_join(client->thread, NULL);
3531 client->thread = AST_PTHREADT_NULL;
3532 }
3533
3534 if (client->mwi_sub) {
3535 client->mwi_sub = stasis_unsubscribe_and_join(client->mwi_sub);
3536 xmpp_pubsub_unsubscribe(client, "message_waiting");
3537 }
3538
3539 if (client->device_state_sub) {
3541 xmpp_pubsub_unsubscribe(client, "device_state");
3542 }
3543
3544#ifdef HAVE_OPENSSL
3545 if (client->stream_flags & SECURE) {
3546 SSL_shutdown(client->ssl_session);
3547 SSL_CTX_free(client->ssl_context);
3548 SSL_free(client->ssl_session);
3549 }
3550
3551 client->stream_flags = 0;
3552#endif
3553
3554 if (client->parser) {
3555 iks_disconnect(client->parser);
3556 }
3557
3559
3560 return 0;
3561}
#define AST_PTHREADT_NULL
Definition: lock.h:66
static void xmpp_pubsub_unsubscribe(struct ast_xmpp_client *client, const char *node)
Unsubscribe from a PubSub node.
Definition: res_xmpp.c:1385
static void xmpp_client_change_state(struct ast_xmpp_client *client, int state)
Internal function which changes the XMPP client state.
Definition: res_xmpp.c:596
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1134
pthread_t thread
Definition: xmpp.h:139
struct stasis_subscription * mwi_sub
Definition: xmpp.h:144
iksparser * parser
Definition: xmpp.h:127
struct stasis_subscription * device_state_sub
Definition: xmpp.h:146
@ XMPP_STATE_DISCONNECTED
Definition: xmpp.h:73
@ XMPP_STATE_DISCONNECTING
Definition: xmpp.h:72

References AST_PTHREADT_NULL, ast_xmpp_client::device_state_sub, ast_xmpp_client::mwi_sub, NULL, ast_xmpp_client::parser, stasis_unsubscribe_and_join(), ast_xmpp_client::thread, xmpp_client_change_state(), xmpp_pubsub_unsubscribe(), XMPP_STATE_DISCONNECTED, and XMPP_STATE_DISCONNECTING.

Referenced by xmpp_client_config_post_apply(), xmpp_client_destructor(), xmpp_client_reconnect(), and xmpp_client_thread().

◆ ast_xmpp_client_find()

struct ast_xmpp_client * ast_xmpp_client_find ( const char *  name)

Find an XMPP client connection using a given name.

Parameters
nameName of the client connection
Return values
non-NULLon success
NULLon failure
Note
This will return the client connection with the reference count incremented by one.

Definition at line 881 of file res_xmpp.c.

882{
884 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
885
886 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
887 return NULL;
888 }
889
890 ao2_ref(clientcfg->client, +1);
891 return clientcfg->client;
892}

References ao2_cleanup, ao2_global_obj_ref, ao2_ref, globals, name, NULL, RAII_VAR, and xmpp_config_find().

Referenced by custom_connection_handler().

◆ ast_xmpp_client_lock()

void ast_xmpp_client_lock ( struct ast_xmpp_client client)

Lock an XMPP client connection.

Parameters
clientPointer to the client

Definition at line 899 of file res_xmpp.c.

900{
901 ao2_lock(client);
902}
#define ao2_lock(a)
Definition: astobj2.h:717

References ao2_lock.

Referenced by ast_xmpp_chatroom_invite(), xmpp_client_authenticate_digest(), xmpp_client_authenticating(), xmpp_client_send_disco_info_request(), xmpp_component_register_set_hook(), xmpp_pak_message(), xmpp_ping_request(), and xmpp_pubsub_iq_create().

◆ ast_xmpp_client_send()

int ast_xmpp_client_send ( struct ast_xmpp_client client,
iks *  stanza 
)

Send an XML stanza out using an established XMPP client connection.

Parameters
clientPointer to the client
stanzaPointer to the Iksemel stanza
Return values
0on success
-1on failure

Definition at line 2534 of file res_xmpp.c.

2535{
2536 return xmpp_client_send_raw_message(client, iks_string(iks_stack(stanza), stanza));
2537}
static int xmpp_client_send_raw_message(struct ast_xmpp_client *client, const char *message)
Internal function which sends a raw message.
Definition: res_xmpp.c:2489

References xmpp_client_send_raw_message().

Referenced by ast_xmpp_chatroom_invite(), jingle_send_error_response(), jingle_send_response(), jingle_send_session_action(), jingle_send_session_info(), jingle_send_session_terminate(), jingle_send_transport_info(), xmpp_client_authenticate_digest(), xmpp_client_authenticate_sasl(), xmpp_client_authenticating(), xmpp_client_send_disco_info_request(), xmpp_client_send_message(), xmpp_client_service_discovery_get_hook(), xmpp_client_set_group_presence(), xmpp_client_set_presence(), xmpp_client_subscribe_user(), xmpp_client_unsubscribe_user(), xmpp_component_register_get_hook(), xmpp_component_register_set_hook(), xmpp_component_service_discovery_get_hook(), xmpp_component_service_discovery_items_hook(), xmpp_connect_hook(), xmpp_pak_s10n(), xmpp_ping_request(), xmpp_pubsub_create_affiliations(), xmpp_pubsub_create_node(), xmpp_pubsub_delete_node(), xmpp_pubsub_handle_error(), xmpp_pubsub_publish_device_state(), xmpp_pubsub_publish_mwi(), xmpp_pubsub_purge_nodes(), xmpp_pubsub_request_nodes(), xmpp_pubsub_subscribe(), and xmpp_pubsub_unsubscribe().

◆ ast_xmpp_client_send_message()

int ast_xmpp_client_send_message ( struct ast_xmpp_client client,
const char *  user,
const char *  message 
)

Send a message to a given user using an established XMPP client connection.

Parameters
clientPointer to the client
userUser the message should be sent to
messageThe message to send
Return values
0on success
-1on failure

Definition at line 938 of file res_xmpp.c.

939{
940 return xmpp_client_send_message(client, 0, NULL, user, message);
941}

References NULL, and xmpp_client_send_message().

Referenced by jingle_sendtext(), manager_jabber_send(), xmpp_send_cb(), and xmpp_send_exec().

◆ ast_xmpp_client_unlock()

void ast_xmpp_client_unlock ( struct ast_xmpp_client client)

Unlock an XMPP client connection.

Parameters
clientPointer to the client

Definition at line 904 of file res_xmpp.c.

905{
906 ao2_unlock(client);
907}
#define ao2_unlock(a)
Definition: astobj2.h:729

References ao2_unlock.

Referenced by ast_xmpp_chatroom_invite(), xmpp_client_authenticate_digest(), xmpp_client_authenticating(), xmpp_client_send_disco_info_request(), xmpp_component_register_set_hook(), xmpp_pak_message(), xmpp_ping_request(), and xmpp_pubsub_iq_create().

◆ ast_xmpp_client_unref()

void ast_xmpp_client_unref ( struct ast_xmpp_client client)

Release XMPP client connection reference.

Parameters
clientPointer to the client

Definition at line 894 of file res_xmpp.c.

895{
896 ao2_ref(client, -1);
897}

References ao2_ref.

Referenced by jingle_endpoint_destructor(), and jingle_session_destructor().

◆ ast_xmpp_increment_mid()

void ast_xmpp_increment_mid ( char *  mid)

Helper function which increments the message identifier.

Parameters
midPointer to a string containing the message identifier

Definition at line 1025 of file res_xmpp.c.

1026{
1027 int i = 0;
1028
1029 for (i = strlen(mid) - 1; i >= 0; i--) {
1030 if (mid[i] != 'z') {
1031 mid[i] = mid[i] + 1;
1032 i = 0;
1033 } else {
1034 mid[i] = 'a';
1035 }
1036 }
1037}

Referenced by ast_xmpp_chatroom_invite(), jingle_send_session_action(), jingle_send_session_info(), jingle_send_session_terminate(), jingle_send_transport_info(), xmpp_client_authenticate_digest(), xmpp_client_authenticating(), xmpp_client_send_disco_info_request(), xmpp_component_register_set_hook(), xmpp_ping_request(), and xmpp_pubsub_iq_create().

◆ cached_devstate_cb()

static int cached_devstate_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 1571 of file res_xmpp.c.

1572{
1573 struct stasis_message *msg = obj;
1574 struct ast_xmpp_client *client = arg;
1575 xmpp_pubsub_devstate_cb(client, client->device_state_sub, msg);
1576 return 0;
1577}
static void xmpp_pubsub_devstate_cb(void *data, struct stasis_subscription *sub, struct stasis_message *msg)
Callback function for device state events.
Definition: res_xmpp.c:1362
XMPP Client Connection.
Definition: xmpp.h:119

References ast_xmpp_client::device_state_sub, and xmpp_pubsub_devstate_cb().

Referenced by xmpp_init_event_distribution().

◆ client_bitfield_handler()

static int client_bitfield_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 4525 of file res_xmpp.c.

4526{
4527 struct ast_xmpp_client_config *cfg = obj;
4528
4529 if (!strcasecmp(var->name, "debug")) {
4530 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_DEBUG);
4531 } else if (!strcasecmp(var->name, "type")) {
4532 ast_set2_flag(&cfg->flags, !strcasecmp(var->value, "component") ? 1 : 0, XMPP_COMPONENT);
4533 } else if (!strcasecmp(var->name, "distribute_events")) {
4535 } else if (!strcasecmp(var->name, "usetls")) {
4536 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_USETLS);
4537 } else if (!strcasecmp(var->name, "usesasl")) {
4538 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_USESASL);
4539 } else if (!strcasecmp(var->name, "forceoldssl")) {
4540 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_FORCESSL);
4541 } else if (!strcasecmp(var->name, "keepalive")) {
4543 } else if (!strcasecmp(var->name, "autoprune")) {
4546 } else if (!strcasecmp(var->name, "autoregister")) {
4549 } else if (!strcasecmp(var->name, "auth_policy")) {
4550 ast_set2_flag(&cfg->flags, !strcasecmp(var->value, "accept") ? 1 : 0, XMPP_AUTOACCEPT);
4552 } else if (!strcasecmp(var->name, "sendtodialplan")) {
4554 } else {
4555 return -1;
4556 }
4557
4558 return 0;
4559}
#define var
Definition: ast_expr2f.c:605
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
struct ast_flags flags
Definition: res_xmpp.c:466
struct ast_flags mod_flags
Definition: res_xmpp.c:467
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94

References ast_set2_flag, ast_true(), ast_xmpp_client_config::flags, ast_xmpp_client_config::mod_flags, var, XMPP_AUTOACCEPT, XMPP_AUTOPRUNE, XMPP_AUTOREGISTER, XMPP_COMPONENT, XMPP_DEBUG, XMPP_DISTRIBUTE_EVENTS, XMPP_FORCESSL, XMPP_KEEPALIVE, XMPP_SEND_TO_DIALPLAN, XMPP_USESASL, and XMPP_USETLS.

Referenced by load_module().

◆ client_buddy_handler()

static int client_buddy_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 4590 of file res_xmpp.c.

4591{
4592 struct ast_xmpp_client_config *cfg = obj;
4593 struct ast_xmpp_buddy *buddy;
4594
4595 if ((buddy = ao2_find(cfg->buddies, var->value, OBJ_KEY))) {
4596 ao2_ref(buddy, -1);
4597 return -1;
4598 }
4599
4600 if (!(buddy = xmpp_client_create_buddy(cfg->buddies, var->value))) {
4601 return -1;
4602 }
4603
4604 ao2_ref(buddy, -1);
4605
4606 return 0;
4607}
#define OBJ_KEY
Definition: astobj2.h:1151
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
static struct ast_xmpp_buddy * xmpp_client_create_buddy(struct ao2_container *container, const char *id)
Internal function which creates a buddy on a client.
Definition: res_xmpp.c:2163
XMPP Buddy.
Definition: xmpp.h:112

References ao2_find, ao2_ref, ast_xmpp_client_config::buddies, OBJ_KEY, var, and xmpp_client_create_buddy().

Referenced by load_module().

◆ client_status_handler()

static int client_status_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 4561 of file res_xmpp.c.

4562{
4563 struct ast_xmpp_client_config *cfg = obj;
4564
4565 if (!strcasecmp(var->value, "unavailable")) {
4566 cfg->status = IKS_SHOW_UNAVAILABLE;
4567 } else if (!strcasecmp(var->value, "available") || !strcasecmp(var->value, "online")) {
4568 cfg->status = IKS_SHOW_AVAILABLE;
4569 } else if (!strcasecmp(var->value, "chat") || !strcasecmp(var->value, "chatty")) {
4570 cfg->status = IKS_SHOW_CHAT;
4571 } else if (!strcasecmp(var->value, "away")) {
4572 cfg->status = IKS_SHOW_AWAY;
4573 } else if (!strcasecmp(var->value, "xa") || !strcasecmp(var->value, "xaway")) {
4574 cfg->status = IKS_SHOW_XA;
4575 } else if (!strcasecmp(var->value, "dnd")) {
4576 cfg->status = IKS_SHOW_DND;
4577 } else if (!strcasecmp(var->value, "invisible")) {
4578#ifdef IKS_SHOW_INVISIBLE
4579 cfg->status = IKS_SHOW_INVISIBLE;
4580#else
4581 cfg->status = IKS_SHOW_DND;
4582#endif
4583 } else {
4584 return -1;
4585 }
4586
4587 return 0;
4588}
enum ikshowtype status
Definition: res_xmpp.c:468

References ast_xmpp_client_config::status, and var.

Referenced by load_module().

◆ CONFIG_INFO_STANDARD()

CONFIG_INFO_STANDARD ( cfg_info  ,
globals  ,
xmpp_config_alloc  ,
files = ACO_FILES(&res_xmpp_conf),
post_apply_config = xmpp_config_post_apply 
)

◆ delete_old_messages()

static int delete_old_messages ( struct ast_xmpp_client client,
char *  from 
)
static

Definition at line 2092 of file res_xmpp.c.

2093{
2095 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2096 int deleted = 0, isold = 0;
2097 struct ast_xmpp_message *message = NULL;
2098
2099 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
2100 return 0;
2101 }
2102
2103 AST_LIST_LOCK(&client->messages);
2105 if (isold) {
2106 if (!from || !strncasecmp(from, message->from, strlen(from))) {
2109 deleted++;
2110 }
2111 } else if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= clientcfg->message_timeout) {
2112 isold = 1;
2113 if (!from || !strncasecmp(from, message->from, strlen(from))) {
2116 deleted++;
2117 }
2118 }
2119 }
2121 AST_LIST_UNLOCK(&client->messages);
2122
2123 return deleted;
2124}
struct ast_xmpp_client::@290 messages
const ast_string_field name
Definition: xmpp.h:123
char * from
Definition: xmpp.h:102
struct ast_xmpp_message::@289 list

References ao2_cleanup, ao2_global_obj_ref, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_tvdiff_sec(), ast_tvnow(), ast_xmpp_message::from, globals, ast_xmpp_message::list, ast_xmpp_client::messages, ast_xmpp_client::name, NULL, RAII_VAR, xmpp_config_find(), and xmpp_message_destroy().

Referenced by xmpp_pak_message().

◆ fetch_access_token()

static int fetch_access_token ( struct ast_xmpp_client_config cfg)
static

Definition at line 3824 of file res_xmpp.c.

3825{
3826 RAII_VAR(char *, cmd, NULL, ast_free);
3827 char cBuf[1024] = "";
3828 const char *url = "https://www.googleapis.com/oauth2/v3/token";
3829 struct ast_json_error error;
3830 RAII_VAR(struct ast_json *, jobj, NULL, ast_json_unref);
3831
3832 if (ast_asprintf(&cmd,
3833 "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
3834 url, cfg->oauth_clientid, cfg->oauth_secret, cfg->refresh_token) < 0) {
3835 return -1;
3836 }
3837
3838 ast_debug(2, "Performing OAuth 2.0 authentication for client '%s' using command: %s\n",
3839 cfg->name, cmd);
3840
3841 if (ast_func_read(NULL, cmd, cBuf, sizeof(cBuf) - 1)) {
3842 ast_log(LOG_ERROR, "CURL is unavailable. This is required for OAuth 2.0 authentication of XMPP client '%s'. Please ensure it is loaded.\n",
3843 cfg->name);
3844 return -1;
3845 }
3846
3847 ast_debug(2, "OAuth 2.0 authentication for client '%s' returned: %s\n", cfg->name, cBuf);
3848
3849 jobj = ast_json_load_string(cBuf, &error);
3850 if (jobj) {
3851 const char *token = ast_json_string_get(ast_json_object_get(jobj, "access_token"));
3852 if (token) {
3853 ast_string_field_set(cfg, password, token);
3854 return 0;
3855 }
3856 }
3857
3858 ast_log(LOG_ERROR, "An error occurred while performing OAuth 2.0 authentication for client '%s': %s\n", cfg->name, cBuf);
3859
3860 return -1;
3861}
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_load_string(const char *input, struct ast_json_error *error)
Parse null terminated string into a JSON object or array.
Definition: json.c:567
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
static char url[512]
JSON parsing error information.
Definition: json.h:887
Abstract JSON element (object, array, string, int, ...).
const ast_string_field oauth_clientid
Definition: res_xmpp.c:462
const ast_string_field oauth_secret
Definition: res_xmpp.c:462
const ast_string_field name
Definition: res_xmpp.c:462
const ast_string_field refresh_token
Definition: res_xmpp.c:462
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_asprintf, ast_debug, ast_free, ast_func_read(), ast_json_load_string(), ast_json_object_get(), ast_json_string_get(), ast_json_unref(), ast_log, ast_string_field_set, error(), LOG_ERROR, ast_xmpp_client_config::name, NULL, ast_xmpp_client_config::oauth_clientid, ast_xmpp_client_config::oauth_secret, RAII_VAR, ast_xmpp_client_config::refresh_token, and url.

Referenced by xmpp_client_reconnect().

◆ get_buddy_status()

static int get_buddy_status ( struct ast_xmpp_client_config clientcfg,
char *  screenname,
char *  resource 
)
static

Definition at line 1630 of file res_xmpp.c.

1631{
1632 int status = BUDDY_OFFLINE;
1633 struct ast_xmpp_resource *res;
1634 struct ast_xmpp_buddy *buddy = ao2_find(clientcfg->client->buddies, screenname, OBJ_KEY);
1635
1636 if (!buddy) {
1637 return BUDDY_NOT_IN_ROSTER;
1638 }
1639
1640 res = ao2_callback(
1641 buddy->resources,
1642 0,
1644 resource);
1645
1646 if (res) {
1647 status = res->status;
1648 }
1649
1650 ao2_cleanup(res);
1651 ao2_cleanup(buddy);
1652
1653 return status;
1654}
jack_status_t status
Definition: app_jack.c:146
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
static int xmpp_resource_immediate(void *obj, void *arg, int flags)
Internal astobj2 callback function which returns the first resource, which is the highest priority on...
Definition: res_xmpp.c:1622
static int xmpp_resource_cmp(void *obj, void *arg, int flags)
Comparator function for XMPP resource.
Definition: res_xmpp.c:853
#define BUDDY_NOT_IN_ROSTER
Definition: res_xmpp.c:1628
#define BUDDY_OFFLINE
Definition: res_xmpp.c:1627
struct ao2_container * resources
Definition: xmpp.h:114
struct ao2_container * buddies
Definition: xmpp.h:137
XMPP Resource.
Definition: xmpp.h:92

References ao2_callback, ao2_cleanup, ao2_find, ast_strlen_zero(), ast_xmpp_client::buddies, BUDDY_NOT_IN_ROSTER, BUDDY_OFFLINE, ast_xmpp_client_config::client, OBJ_KEY, ast_xmpp_buddy::resources, status, ast_xmpp_resource::status, xmpp_resource_cmp(), and xmpp_resource_immediate().

Referenced by acf_jabberstatus_read().

◆ global_bitfield_handler()

static int global_bitfield_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
)
static

Definition at line 4502 of file res_xmpp.c.

4503{
4504 struct ast_xmpp_global_config *global = obj;
4505
4506 if (!strcasecmp(var->name, "debug")) {
4507 debug = ast_true(var->value);
4508 } else if (!strcasecmp(var->name, "autoprune")) {
4509 ast_set2_flag(&global->general, ast_true(var->value), XMPP_AUTOPRUNE);
4510 } else if (!strcasecmp(var->name, "autoregister")) {
4511 ast_set2_flag(&global->general, ast_true(var->value), XMPP_AUTOREGISTER);
4512 } else if (!strcasecmp(var->name, "auth_policy")) {
4513 ast_set2_flag(&global->general, !strcasecmp(var->value, "accept") ? 1 : 0, XMPP_AUTOACCEPT);
4514 } else if (!strcasecmp(var->name, "collection_nodes")) {
4515 ast_set2_flag(&global->pubsub, ast_true(var->value), XMPP_XEP0248);
4516 } else if (!strcasecmp(var->name, "pubsub_autocreate")) {
4518 } else {
4519 return -1;
4520 }
4521
4522 return 0;
4523}
static int debug
Global debug status.
Definition: res_xmpp.c:441
XMPP Global Configuration.
Definition: res_xmpp.c:444
static struct aco_type global
Definition: test_config.c:1445

References ast_set2_flag, ast_true(), debug, global, var, XMPP_AUTOACCEPT, XMPP_AUTOPRUNE, XMPP_AUTOREGISTER, XMPP_PUBSUB_AUTOCREATE, and XMPP_XEP0248.

Referenced by load_module().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 4619 of file res_xmpp.c.

4620{
4621 if (aco_info_init(&cfg_info)) {
4623 }
4624
4627 aco_option_register_custom(&cfg_info, "autoregister", ACO_EXACT, global_options, "yes", global_bitfield_handler, 0);
4628 aco_option_register_custom(&cfg_info, "collection_nodes", ACO_EXACT, global_options, "no", global_bitfield_handler, 0);
4629 aco_option_register_custom(&cfg_info, "pubsub_autocreate", ACO_EXACT, global_options, "no", global_bitfield_handler, 0);
4630 aco_option_register_custom(&cfg_info, "auth_policy", ACO_EXACT, global_options, "accept", global_bitfield_handler, 0);
4631
4634 aco_option_register(&cfg_info, "refresh_token", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, refresh_token));
4635 aco_option_register(&cfg_info, "oauth_clientid", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, oauth_clientid));
4636 aco_option_register(&cfg_info, "oauth_secret", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, oauth_secret));
4638 aco_option_register(&cfg_info, "statusmessage", ACO_EXACT, client_options, "Online and Available", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, statusmsg));
4639 aco_option_register(&cfg_info, "pubsub_node", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, pubsubnode));
4642 aco_option_register(&cfg_info, "port", ACO_EXACT, client_options, "5222", OPT_UINT_T, 0, FLDSET(struct ast_xmpp_client_config, port));
4643 aco_option_register(&cfg_info, "timeout", ACO_EXACT, client_options, "5", OPT_UINT_T, 0, FLDSET(struct ast_xmpp_client_config, message_timeout));
4644
4645 /* Global options that can be overridden per client must not specify a default */
4649
4652 aco_option_register_custom(&cfg_info, "distribute_events", ACO_EXACT, client_options, "no", client_bitfield_handler, 0);
4655 aco_option_register_custom(&cfg_info, "forceoldssl", ACO_EXACT, client_options, "no", client_bitfield_handler, 0);
4657 aco_option_register_custom(&cfg_info, "sendtodialplan", ACO_EXACT, client_options, "no", client_bitfield_handler, 0);
4658 aco_option_register_custom(&cfg_info, "status", ACO_EXACT, client_options, "available", client_status_handler, 0);
4660
4661 if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
4662 aco_info_destroy(&cfg_info);
4664 }
4665
4667
4672
4677
4680
4682 ast_log(LOG_WARNING, "Entity ID is not set. The distributing device state or MWI will not work.\n");
4683 }
4684
4686}
static int priority
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ ACO_EXACT
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
struct aco_type * global_options[]
Definition: res_xmpp.c:808
static int xmpp_send_exec(struct ast_channel *chan, const char *data)
Definition: res_xmpp.c:1838
static const char * app_ajijoin
Definition: res_xmpp.c:519
static int global_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4502
static struct ast_custom_function jabberstatus_function
Definition: res_xmpp.c:1706
static const char * app_ajisendgroup
Definition: res_xmpp.c:517
struct aco_type * client_options[]
Definition: res_xmpp.c:821
static int client_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4525
static int manager_jabber_send(struct mansession *s, const struct message *m)
Definition: res_xmpp.c:3924
static int xmpp_join_exec(struct ast_channel *chan, const char *data)
Application to join a chat room.
Definition: res_xmpp.c:1718
static const char * app_ajileave
Definition: res_xmpp.c:520
static const char * app_ajisend
Definition: res_xmpp.c:516
static struct ast_cli_entry xmpp_cli[]
Definition: res_xmpp.c:4470
static int client_buddy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4590
static struct ast_custom_function jabberreceive_function
Definition: res_xmpp.c:2079
static const struct ast_msg_tech msg_tech
Definition: res_xmpp.c:2157
static int client_status_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4561
static int xmpp_leave_exec(struct ast_channel *chan, const char *data)
Application to leave a chat room.
Definition: res_xmpp.c:1777
static int xmpp_sendgroup_exec(struct ast_channel *chan, const char *data)
Application to send a message to a groupchat.
Definition: res_xmpp.c:1879
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition: utils.c:3099
#define ARRAY_LEN(a)
Definition: utils.h:666
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93

References ACO_EXACT, aco_info_destroy(), aco_info_init(), aco_option_register, aco_option_register_custom, aco_process_config(), ACO_PROCESS_ERROR, app_ajijoin, app_ajileave, app_ajisend, app_ajisendgroup, ARRAY_LEN, ast_cli_register_multiple, ast_cond_init, ast_custom_function_register, ast_eid_default, ast_eid_is_empty(), ast_log, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_msg_tech_register(), ast_mutex_init, ast_register_application_xml, client_bitfield_handler(), client_buddy_handler(), client_options, client_status_handler(), voicemailpwcheck::context, EVENT_FLAG_SYSTEM, FLDSET, global_bitfield_handler(), global_options, jabberreceive_function, jabberstatus_function, LOG_WARNING, manager_jabber_send(), message_received_condition, messagelock, msg_tech, NULL, OPT_STRINGFIELD_T, OPT_UINT_T, priority, STRFLDSET, xmpp_cli, xmpp_join_exec(), xmpp_leave_exec(), xmpp_send_exec(), and xmpp_sendgroup_exec().

◆ manager_jabber_send()

static int manager_jabber_send ( struct mansession s,
const struct message m 
)
static

Definition at line 3924 of file res_xmpp.c.

3925{
3927 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3928 const char *id = astman_get_header(m, "ActionID");
3929 const char *jabber = astman_get_header(m, "Jabber");
3930 const char *screenname = astman_get_header(m, "ScreenName");
3931 const char *message = astman_get_header(m, "Message");
3932
3933 if (ast_strlen_zero(jabber)) {
3934 astman_send_error(s, m, "No transport specified");
3935 return 0;
3936 }
3937 if (ast_strlen_zero(screenname)) {
3938 astman_send_error(s, m, "No ScreenName specified");
3939 return 0;
3940 }
3941 if (ast_strlen_zero(message)) {
3942 astman_send_error(s, m, "No Message specified");
3943 return 0;
3944 }
3945
3946 astman_send_ack(s, m, "Attempting to send Jabber Message");
3947
3948 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, jabber))) {
3949 astman_send_error(s, m, "Could not find Sender");
3950 return 0;
3951 }
3952
3953 if (strchr(screenname, '@') && !ast_xmpp_client_send_message(clientcfg->client, screenname, message)) {
3954 astman_append(s, "Response: Success\r\n");
3955 } else {
3956 astman_append(s, "Response: Error\r\n");
3957 }
3958
3959 if (!ast_strlen_zero(id)) {
3960 astman_append(s, "ActionID: %s\r\n", id);
3961 }
3962
3963 astman_append(s, "\r\n");
3964
3965 return 0;
3966}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3381
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3413
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3042
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3302
int ast_xmpp_client_send_message(struct ast_xmpp_client *client, const char *user, const char *message)
Send a message to a given user using an established XMPP client connection.
Definition: res_xmpp.c:938

References ao2_cleanup, ao2_global_obj_ref, ast_strlen_zero(), ast_xmpp_client_send_message(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), globals, NULL, RAII_VAR, and xmpp_config_find().

Referenced by load_module().

◆ reload()

static int reload ( void  )
static

Definition at line 4688 of file res_xmpp.c.

4689{
4690 if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
4692 }
4693
4694 return 0;
4695}

References aco_process_config(), ACO_PROCESS_ERROR, and AST_MODULE_LOAD_DECLINE.

◆ sleep_with_backoff()

static void sleep_with_backoff ( unsigned int *  sleep_time)
static

Definition at line 3716 of file res_xmpp.c.

3717{
3718 /* We're OK with our thread dying here */
3719 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
3720
3721 sleep(*sleep_time);
3722 *sleep_time = MIN(60, *sleep_time * 2);
3723
3724 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
3725}
#define MIN(a, b)
Definition: utils.h:231

References MIN, and NULL.

Referenced by xmpp_client_thread().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4481 of file res_xmpp.c.

4482{
4490 ast_manager_unregister("JabberSend");
4493 aco_info_destroy(&cfg_info);
4495
4498
4499 return 0;
4500}
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8041
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_mutex_destroy(a)
Definition: lock.h:188
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static const char * app_ajistatus
Definition: res_xmpp.c:518

References aco_info_destroy(), ao2_global_obj_release, app_ajijoin, app_ajileave, app_ajisend, app_ajisendgroup, app_ajistatus, ARRAY_LEN, ast_cli_unregister_multiple(), ast_cond_destroy, ast_custom_function_unregister(), ast_manager_unregister(), ast_msg_tech_unregister(), ast_mutex_destroy, ast_unregister_application(), globals, jabberreceive_function, jabberstatus_function, message_received_condition, messagelock, msg_tech, and xmpp_cli.

◆ xmpp_action_hook()

static int xmpp_action_hook ( void *  data,
int  type,
iks *  node 
)
static

Action hook for when things occur.

Definition at line 3455 of file res_xmpp.c.

3456{
3458 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3459 struct ast_xmpp_client *client = data;
3460 ikspak *pak;
3461 int i;
3462
3463 if (!node) {
3464 ast_log(LOG_ERROR, "xmpp_action_hook was called without a packet\n");
3465 return IKS_HOOK;
3466 }
3467
3468 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
3469 return IKS_HOOK;
3470 }
3471
3472 /* If the client is disconnecting ignore everything */
3473 if (client->state == XMPP_STATE_DISCONNECTING) {
3474 return IKS_HOOK;
3475 }
3476
3477 pak = iks_packet(node);
3478
3479 /* work around iksemel's impossibility to recognize node names
3480 * containing a colon. Set the namespace of the corresponding
3481 * node accordingly. */
3482 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) {
3483 char *node_ns = NULL;
3484 char attr[XMPP_MAX_ATTRLEN];
3485 char *node_name = iks_name(iks_child(node));
3486 char *aux = strchr(node_name, ':') + 1;
3487 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name);
3488 node_ns = iks_find_attrib(iks_child(node), attr);
3489 if (node_ns) {
3490 pak->ns = node_ns;
3491 pak->query = iks_child(node);
3492 }
3493 }
3494
3495 /* Process through any state handlers */
3496 for (i = 0; i < ARRAY_LEN(xmpp_state_handlers); i++) {
3497 if ((xmpp_state_handlers[i].state == client->state) && (xmpp_state_handlers[i].component == (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) ? 1 : 0))) {
3498 if (xmpp_state_handlers[i].handler(client, clientcfg, type, node)) {
3499 /* If the handler wants us to stop now, do so */
3500 return IKS_HOOK;
3501 }
3502 break;
3503 }
3504 }
3505
3506 /* Process through any PAK handlers */
3507 for (i = 0; i < ARRAY_LEN(xmpp_pak_handlers); i++) {
3508 if (xmpp_pak_handlers[i].type == pak->type) {
3509 if (xmpp_pak_handlers[i].handler(client, clientcfg, node, pak)) {
3510 /* If the handler wants us to stop now, do so */
3511 return IKS_HOOK;
3512 }
3513 break;
3514 }
3515 }
3516
3517 /* Send the packet through the filter in case any filters want to process it */
3518 iks_filter_packet(client->filter, pak);
3519
3520 iks_delete(node);
3521
3522 return IKS_OK;
3523}
static const char type[]
Definition: chan_ooh323.c:109
static const struct xmpp_state_handler xmpp_state_handlers[]
static const struct xmpp_pak_handler xmpp_pak_handlers[]
enum xmpp_state state
Definition: xmpp.h:136
iksfilter * filter
Definition: xmpp.h:128
Definition: test_heap.c:38
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define XMPP_MAX_ATTRLEN
Maximum size of an attribute.
Definition: xmpp.h:68

References ao2_cleanup, ao2_global_obj_ref, ARRAY_LEN, ast_log, ast_test_flag, xmpp_state_handler::component, ast_xmpp_client::filter, globals, handler(), LOG_ERROR, ast_xmpp_client::name, NULL, RAII_VAR, ast_xmpp_client::state, type, XMPP_COMPONENT, xmpp_config_find(), XMPP_MAX_ATTRLEN, xmpp_pak_handlers, XMPP_STATE_DISCONNECTING, and xmpp_state_handlers.

Referenced by xmpp_client_config_post_apply().

◆ xmpp_buddy_cmp()

static int xmpp_buddy_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Comparator function for XMPP buddy.

Definition at line 587 of file res_xmpp.c.

588{
589 struct ast_xmpp_buddy *buddy1 = obj, *buddy2 = arg;
590 const char *id = arg;
591
592 return !strcmp(buddy1->id, flags & OBJ_KEY ? id : buddy2->id) ? CMP_MATCH | CMP_STOP : 0;
593}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
char id[XMPP_MAX_JIDLEN]
Definition: xmpp.h:113

References CMP_MATCH, CMP_STOP, ast_xmpp_buddy::id, and OBJ_KEY.

Referenced by ast_xmpp_client_config_alloc(), and xmpp_client_alloc().

◆ xmpp_buddy_destructor()

static void xmpp_buddy_destructor ( void *  obj)
static

Destructor callback function for XMPP buddy.

Definition at line 862 of file res_xmpp.c.

863{
864 struct ast_xmpp_buddy *buddy = obj;
865
866 if (buddy->resources) {
867 ao2_ref(buddy->resources, -1);
868 }
869}

References ao2_ref, and ast_xmpp_buddy::resources.

Referenced by xmpp_client_create_buddy().

◆ xmpp_buddy_hash()

static int xmpp_buddy_hash ( const void *  obj,
const int  flags 
)
static

Hashing function for XMPP buddy.

Definition at line 578 of file res_xmpp.c.

579{
580 const struct ast_xmpp_buddy *buddy = obj;
581 const char *id = obj;
582
583 return ast_str_hash(flags & OBJ_KEY ? id : buddy->id);
584}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259

References ast_str_hash(), ast_xmpp_buddy::id, and OBJ_KEY.

Referenced by ast_xmpp_client_config_alloc(), and xmpp_client_alloc().

◆ xmpp_cli_create_collection()

static char * xmpp_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.

Returns
char *

Definition at line 4218 of file res_xmpp.c.

4219{
4221 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4222 const char *name, *collection_name;
4223
4224 switch (cmd) {
4225 case CLI_INIT:
4226 e->command = "xmpp create collection";
4227 e->usage =
4228 "Usage: xmpp create collection <connection> <collection>\n"
4229 " Creates a PubSub collection node using the account\n"
4230 " as configured in xmpp.conf.\n";
4231 return NULL;
4232 case CLI_GENERATE:
4233 return NULL;
4234 }
4235
4236 if (a->argc != 5) {
4237 return CLI_SHOWUSAGE;
4238 }
4239 name = a->argv[3];
4240 collection_name = a->argv[4];
4241
4242 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4243 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4244 return CLI_FAILURE;
4245 }
4246
4247 ast_cli(a->fd, "Creating test PubSub node collection.\n");
4248
4249 xmpp_pubsub_create_collection(clientcfg->client, collection_name);
4250
4251 return CLI_SUCCESS;
4252}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
static void xmpp_pubsub_create_collection(struct ast_xmpp_client *client, const char *collection_name)
Create a PubSub collection node.
Definition: res_xmpp.c:1244
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ao2_cleanup, ao2_global_obj_ref, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, globals, name, NULL, RAII_VAR, ast_cli_entry::usage, xmpp_config_find(), and xmpp_pubsub_create_collection().

◆ xmpp_cli_create_leafnode()

static char * xmpp_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.

Returns
char *

Definition at line 4258 of file res_xmpp.c.

4259{
4261 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4262 const char *name, *collection_name, *leaf_name;
4263
4264 switch (cmd) {
4265 case CLI_INIT:
4266 e->command = "xmpp create leaf";
4267 e->usage =
4268 "Usage: xmpp create leaf <connection> <collection> <leaf>\n"
4269 " Creates a PubSub leaf node using the account\n"
4270 " as configured in xmpp.conf.\n";
4271 return NULL;
4272 case CLI_GENERATE:
4273 return NULL;
4274 }
4275
4276 if (a->argc != 6) {
4277 return CLI_SHOWUSAGE;
4278 }
4279 name = a->argv[3];
4280 collection_name = a->argv[4];
4281 leaf_name = a->argv[5];
4282
4283 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4284 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4285 return CLI_FAILURE;
4286 }
4287
4288 ast_cli(a->fd, "Creating test PubSub node collection.\n");
4289
4290 xmpp_pubsub_create_leaf(clientcfg->client, collection_name, leaf_name);
4291
4292 return CLI_SUCCESS;
4293}
static void xmpp_pubsub_create_leaf(struct ast_xmpp_client *client, const char *collection_name, const char *leaf_name)
Create a PubSub leaf node.
Definition: res_xmpp.c:1256

References a, ao2_cleanup, ao2_global_obj_ref, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, globals, name, NULL, RAII_VAR, ast_cli_entry::usage, xmpp_config_find(), and xmpp_pubsub_create_leaf().

◆ xmpp_cli_delete_pubsub_node()

static char * xmpp_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.

Parameters
epointer to ast_cli_entry structure
cmd
apointer to ast_cli_args structure
Returns
char *

Definition at line 4180 of file res_xmpp.c.

4182{
4184 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4185 const char *name;
4186
4187 switch (cmd) {
4188 case CLI_INIT:
4189 e->command = "xmpp delete node";
4190 e->usage =
4191 "Usage: xmpp delete node <connection> <node>\n"
4192 " Deletes a node on PubSub server\n"
4193 " as configured in xmpp.conf.\n";
4194 return NULL;
4195 case CLI_GENERATE:
4196 return NULL;
4197 }
4198
4199 if (a->argc != 5) {
4200 return CLI_SHOWUSAGE;
4201 }
4202 name = a->argv[3];
4203
4204 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4205 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4206 return CLI_FAILURE;
4207 }
4208
4209 xmpp_pubsub_delete_node(clientcfg->client, a->argv[4]);
4210
4211 return CLI_SUCCESS;
4212}
static void xmpp_pubsub_delete_node(struct ast_xmpp_client *client, const char *node_name)
Delete a PubSub node.
Definition: res_xmpp.c:1222

References a, ao2_cleanup, ao2_global_obj_ref, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, globals, name, NULL, RAII_VAR, ast_cli_entry::usage, xmpp_config_find(), and xmpp_pubsub_delete_node().

◆ xmpp_cli_list_pubsub_nodes()

static char * xmpp_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.

Parameters
epointer to ast_cli_entry structure
cmd
apointer to ast_cli_args structure
Returns
char *

Definition at line 4049 of file res_xmpp.c.

4051{
4053 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4054 const char *name = NULL, *collection = NULL;
4055
4056 switch (cmd) {
4057 case CLI_INIT:
4058 e->command = "xmpp list nodes";
4059 e->usage =
4060 "Usage: xmpp list nodes <connection> [collection]\n"
4061 " Lists the user's nodes on the respective connection\n"
4062 " ([connection] as configured in xmpp.conf.)\n";
4063 return NULL;
4064 case CLI_GENERATE:
4065 return NULL;
4066 }
4067
4068 if (a->argc > 5 || a->argc < 4) {
4069 return CLI_SHOWUSAGE;
4070 } else if (a->argc == 4 || a->argc == 5) {
4071 name = a->argv[3];
4072 }
4073
4074 if (a->argc == 5) {
4075 collection = a->argv[4];
4076 }
4077
4078 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4079 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4080 return CLI_FAILURE;
4081 }
4082
4083 ast_cli(a->fd, "Listing pubsub nodes.\n");
4084
4085 xmpp_pubsub_request_nodes(clientcfg->client, collection);
4086
4087 return CLI_SUCCESS;
4088}
static void xmpp_pubsub_request_nodes(struct ast_xmpp_client *client, const char *collection)
Request item list from pubsub.
Definition: res_xmpp.c:4025

References a, ao2_cleanup, ao2_global_obj_ref, ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, globals, name, NULL, RAII_VAR, ast_cli_entry::usage, xmpp_config_find(), and xmpp_pubsub_request_nodes().

◆ xmpp_cli_purge_pubsub_nodes()

static char * xmpp_cli_purge_pubsub_nodes ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Method to purge PubSub nodes via CLI.

Parameters
epointer to ast_cli_entry structure
cmd
apointer to ast_cli_args structure
Returns
char *

Definition at line 4135 of file res_xmpp.c.

4137{
4139 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4140 const char *name;
4141
4142 switch (cmd) {
4143 case CLI_INIT:
4144 e->command = "xmpp purge nodes";
4145 e->usage =
4146 "Usage: xmpp purge nodes <connection> <node>\n"
4147 " Purges nodes on PubSub server\n"
4148 " as configured in xmpp.conf.\n";
4149 return NULL;
4150 case CLI_GENERATE:
4151 return NULL;
4152 }
4153
4154 if (a->argc != 5) {
4155 return CLI_SHOWUSAGE;
4156 }
4157 name = a->argv[3];
4158
4159 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4160 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4161 return CLI_FAILURE;
4162 }
4163
4164 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
4165 xmpp_pubsub_purge_nodes(clientcfg->client, a->argv[4]);
4166 } else {
4167 xmpp_pubsub_delete_node(clientcfg->client, a->argv[4]);
4168 }
4169
4170 return CLI_SUCCESS;
4171}
static void xmpp_pubsub_purge_nodes(struct ast_xmpp_client *client, const char *collection_name)
Definition: res_xmpp.c:4117

References a, ao2_cleanup, ao2_global_obj_ref, ast_cli(), ast_test_flag, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, globals, name, NULL, RAII_VAR, ast_cli_entry::usage, xmpp_config_find(), xmpp_pubsub_delete_node(), xmpp_pubsub_purge_nodes(), and XMPP_XEP0248.

◆ xmpp_client_alloc()

static struct ast_xmpp_client * xmpp_client_alloc ( const char *  name)
static

Allocator function for ast_xmpp_client.

Definition at line 610 of file res_xmpp.c.

611{
612 struct ast_xmpp_client *client;
613
614 if (!(client = ao2_alloc(sizeof(*client), xmpp_client_destructor))) {
615 return NULL;
616 }
617
619 client->thread = AST_PTHREADT_NULL;
620
621 client->endpoint = ast_endpoint_create("XMPP", name);
622 if (!client->endpoint) {
623 ao2_ref(client, -1);
624 return NULL;
625 }
626
629 if (!client->buddies) {
630 ast_log(LOG_ERROR, "Could not initialize buddy container for '%s'\n", name);
631 ao2_ref(client, -1);
632 return NULL;
633 }
634
635 if (ast_string_field_init(client, 512)) {
636 ast_log(LOG_ERROR, "Could not initialize stringfields for '%s'\n", name);
637 ao2_ref(client, -1);
638 return NULL;
639 }
640
641 if (!(client->stack = iks_stack_new(8192, 8192))) {
642 ast_log(LOG_ERROR, "Could not create an Iksemel stack for '%s'\n", name);
643 ao2_ref(client, -1);
644 return NULL;
645 }
646
648
649 client->timeout = 50;
651 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
652
653 return client;
654}
struct ast_endpoint * ast_endpoint_create(const char *tech, const char *resource)
Create an endpoint struct.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
static void xmpp_client_destructor(void *obj)
Destructor callback function for XMPP client.
Definition: res_xmpp.c:551
int timeout
Definition: xmpp.h:140
struct ast_endpoint * endpoint
Definition: xmpp.h:148
ikstack * stack
Definition: xmpp.h:129

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, ast_copy_string(), ast_endpoint_create(), AST_LIST_HEAD_INIT, ast_log, AST_PTHREADT_NULL, ast_string_field_init, ast_string_field_set, ast_xmpp_client::buddies, BUDDY_BUCKETS, ast_xmpp_client::endpoint, LOG_ERROR, ast_xmpp_client::messages, ast_xmpp_client::mid, name, NULL, ast_xmpp_client::stack, ast_xmpp_client::thread, ast_xmpp_client::timeout, xmpp_buddy_cmp(), xmpp_buddy_hash(), xmpp_client_change_state(), xmpp_client_destructor(), and XMPP_STATE_DISCONNECTED.

Referenced by xmpp_client_find_or_create().

◆ xmpp_client_authenticate()

static int xmpp_client_authenticate ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we need to authenticate.

Definition at line 2757 of file res_xmpp.c.

2758{
2760}
static int xmpp_client_authenticate_digest(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we need to authenticate using non-SASL.
Definition: res_xmpp.c:2654
static int xmpp_client_authenticate_sasl(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we need to authenticate using SASL.
Definition: res_xmpp.c:2692

References ast_test_flag, ast_xmpp_client_config::flags, type, xmpp_client_authenticate_digest(), xmpp_client_authenticate_sasl(), and XMPP_USESASL.

◆ xmpp_client_authenticate_digest()

static int xmpp_client_authenticate_digest ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we need to authenticate using non-SASL.

Definition at line 2654 of file res_xmpp.c.

2655{
2656 iks *iq = NULL, *query = NULL;
2657 char buf[41], sidpass[100];
2658
2659 if (!(iq = iks_new("iq")) || !(query = iks_insert(iq, "query"))) {
2660 ast_log(LOG_ERROR, "Stanzas could not be allocated for authentication on client '%s'\n", client->name);
2661 iks_delete(iq);
2662 return -1;
2663 }
2664
2665 iks_insert_attrib(iq, "type", "set");
2666 iks_insert_cdata(iks_insert(query, "username"), client->jid->user, 0);
2667 iks_insert_cdata(iks_insert(query, "resource"), client->jid->resource, 0);
2668
2669 iks_insert_attrib(query, "xmlns", "jabber:iq:auth");
2670 snprintf(sidpass, sizeof(sidpass), "%s%s", iks_find_attrib(node, "id"), cfg->password);
2671 ast_sha1_hash(buf, sidpass);
2672 iks_insert_cdata(iks_insert(query, "digest"), buf, 0);
2673
2674 ast_xmpp_client_lock(client);
2675 iks_filter_add_rule(client->filter, xmpp_connect_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid, IKS_RULE_DONE);
2676 iks_insert_attrib(iq, "id", client->mid);
2677 ast_xmpp_increment_mid(client->mid);
2678 ast_xmpp_client_unlock(client);
2679
2680 iks_insert_attrib(iq, "to", client->jid->server);
2681
2682 ast_xmpp_client_send(client, iq);
2683
2684 iks_delete(iq);
2685
2687
2688 return 0;
2689}
static int xmpp_connect_hook(void *data, ikspak *pak)
Hook function called when client finishes authenticating with the server.
Definition: res_xmpp.c:2433
const ast_string_field password
Definition: res_xmpp.c:462
iksid * jid
Definition: xmpp.h:126
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: utils.c:266
@ XMPP_STATE_AUTHENTICATING
Definition: xmpp.h:78

References ast_log, ast_sha1_hash(), ast_xmpp_client_lock(), ast_xmpp_client_send(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), buf, ast_xmpp_client::filter, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::mid, ast_xmpp_client::name, NULL, ast_xmpp_client_config::password, xmpp_client_change_state(), xmpp_connect_hook(), and XMPP_STATE_AUTHENTICATING.

Referenced by xmpp_client_authenticate().

◆ xmpp_client_authenticate_sasl()

static int xmpp_client_authenticate_sasl ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we need to authenticate using SASL.

Definition at line 2692 of file res_xmpp.c.

2693{
2694 int features, len = strlen(client->jid->user) + strlen(cfg->password) + 3;
2695 iks *auth;
2696 char combined[len];
2697 char base64[(len + 2) * 4 / 3];
2698
2699 if (strcmp(iks_name(node), "stream:features")) {
2700 /* Ignore anything beside stream features */
2701 return 0;
2702 }
2703
2704 features = iks_stream_features(node);
2705
2706 if ((features & IKS_STREAM_SASL_MD5) && !xmpp_is_secure(client)) {
2707 if (iks_start_sasl(client->parser, IKS_SASL_DIGEST_MD5, (char*)client->jid->user, (char*)cfg->password) != IKS_OK) {
2708 ast_log(LOG_ERROR, "Tried to authenticate client '%s' using SASL DIGEST-MD5 but could not\n", client->name);
2709 return -1;
2710 }
2711
2713 return 0;
2714 }
2715
2716 /* Our only other available option is plain so if they don't support it, bail out now */
2717 if (!(features & IKS_STREAM_SASL_PLAIN)) {
2718 ast_log(LOG_ERROR, "Tried to authenticate client '%s' using SASL PLAIN but server does not support it\n", client->name);
2719 return -1;
2720 }
2721
2722 if (!(auth = iks_new("auth"))) {
2723 ast_log(LOG_ERROR, "Could not allocate memory for SASL PLAIN authentication for client '%s'\n", client->name);
2724 return -1;
2725 }
2726
2727 iks_insert_attrib(auth, "xmlns", IKS_NS_XMPP_SASL);
2728 if (!ast_strlen_zero(cfg->refresh_token)) {
2729 iks_insert_attrib(auth, "mechanism", "X-OAUTH2");
2730 iks_insert_attrib(auth, "auth:service", "oauth2");
2731 iks_insert_attrib(auth, "xmlns:auth", "http://www.google.com/talk/protocol/auth");
2732 } else {
2733 iks_insert_attrib(auth, "mechanism", "PLAIN");
2734 }
2735
2736 if (strchr(client->jid->user, '/')) {
2737 char *user = ast_strdupa(client->jid->user);
2738
2739 snprintf(combined, sizeof(combined), "%c%s%c%s", 0, strsep(&user, "/"), 0, cfg->password);
2740 } else {
2741 snprintf(combined, sizeof(combined), "%c%s%c%s", 0, client->jid->user, 0, cfg->password);
2742 }
2743
2744 ast_base64encode(base64, (const unsigned char *) combined, len - 1, (len + 2) * 4 / 3);
2745 iks_insert_cdata(auth, base64, 0);
2746
2747 ast_xmpp_client_send(client, auth);
2748
2749 iks_delete(auth);
2750
2752
2753 return 0;
2754}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
static int xmpp_is_secure(struct ast_xmpp_client *client)
Helper function which returns whether an XMPP client connection is secure or not.
Definition: res_xmpp.c:872
static char base64[64]
Definition: utils.c:80
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:406

References ast_base64encode(), ast_log, ast_strdupa, ast_strlen_zero(), ast_xmpp_client_send(), base64, ast_xmpp_client::jid, len(), LOG_ERROR, ast_xmpp_client::name, ast_xmpp_client::parser, ast_xmpp_client_config::password, ast_xmpp_client_config::refresh_token, strsep(), xmpp_client_change_state(), xmpp_is_secure(), and XMPP_STATE_AUTHENTICATING.

Referenced by xmpp_client_authenticate().

◆ xmpp_client_authenticating()

static int xmpp_client_authenticating ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we are authenticating.

Definition at line 2763 of file res_xmpp.c.

2764{
2765 int features;
2766
2767 if (!strcmp(iks_name(node), "success")) {
2768 /* Authentication was a success, yay! */
2769 xmpp_send_stream_header(client, cfg, client->jid->server);
2770
2771 return 0;
2772 } else if (!strcmp(iks_name(node), "failure")) {
2773 /* Authentication was a bust, disconnect and reconnect later */
2774 return -1;
2775 } else if (strcmp(iks_name(node), "stream:features")) {
2776 /* Ignore any other responses */
2777 return 0;
2778 }
2779
2780 features = iks_stream_features(node);
2781
2782 if (features & IKS_STREAM_BIND) {
2783 iks *auth;
2784
2785 if (!(auth = iks_make_resource_bind(client->jid))) {
2786 ast_log(LOG_ERROR, "Failed to allocate memory for stream bind on client '%s'\n", client->name);
2787 return -1;
2788 }
2789
2790 ast_xmpp_client_lock(client);
2791 iks_insert_attrib(auth, "id", client->mid);
2792 ast_xmpp_increment_mid(client->mid);
2793 ast_xmpp_client_unlock(client);
2794 ast_xmpp_client_send(client, auth);
2795
2796 iks_delete(auth);
2797
2798 iks_filter_add_rule(client->filter, xmpp_connect_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
2799 }
2800
2801 if (features & IKS_STREAM_SESSION) {
2802 iks *auth;
2803
2804 if (!(auth = iks_make_session())) {
2805 ast_log(LOG_ERROR, "Failed to allocate memory for stream session on client '%s'\n", client->name);
2806 return -1;
2807 }
2808
2809 iks_insert_attrib(auth, "id", "auth");
2810 ast_xmpp_client_lock(client);
2811 ast_xmpp_increment_mid(client->mid);
2812 ast_xmpp_client_unlock(client);
2813 ast_xmpp_client_send(client, auth);
2814
2815 iks_delete(auth);
2816
2817 iks_filter_add_rule(client->filter, xmpp_connect_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "auth", IKS_RULE_DONE);
2818 }
2819
2820 return 0;
2821}
static int xmpp_send_stream_header(struct ast_xmpp_client *client, const struct ast_xmpp_client_config *cfg, const char *to)
Helper function which sends an XMPP stream header to the server.
Definition: res_xmpp.c:2522

References ast_log, ast_xmpp_client_lock(), ast_xmpp_client_send(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), ast_xmpp_client::filter, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::mid, ast_xmpp_client::name, xmpp_connect_hook(), and xmpp_send_stream_header().

◆ xmpp_client_change_state()

static void xmpp_client_change_state ( struct ast_xmpp_client client,
int  state 
)
static

Internal function which changes the XMPP client state.

Definition at line 596 of file res_xmpp.c.

597{
598 if (state == client->state) {
599 return;
600 }
601 client->state = state;
602 if (client->state == XMPP_STATE_DISCONNECTED) {
604 } else if (client->state == XMPP_STATE_CONNECTED) {
606 }
607}
enum cc_state state
Definition: ccss.c:393
@ AST_ENDPOINT_OFFLINE
Definition: endpoints.h:55
@ AST_ENDPOINT_ONLINE
Definition: endpoints.h:57
void ast_endpoint_set_state(struct ast_endpoint *endpoint, enum ast_endpoint_state state)
Updates the state of the given endpoint.
@ XMPP_STATE_CONNECTED
Definition: xmpp.h:80

References AST_ENDPOINT_OFFLINE, AST_ENDPOINT_ONLINE, ast_endpoint_set_state(), ast_xmpp_client::endpoint, ast_xmpp_client::state, state, XMPP_STATE_CONNECTED, and XMPP_STATE_DISCONNECTED.

Referenced by ast_xmpp_client_disconnect(), xmpp_client_alloc(), xmpp_client_authenticate_digest(), xmpp_client_authenticate_sasl(), xmpp_client_reconnect(), xmpp_client_request_tls(), xmpp_client_requested_tls(), xmpp_component_authenticate(), xmpp_component_authenticating(), xmpp_connect_hook(), and xmpp_roster_hook().

◆ xmpp_client_config_merge_buddies()

static int xmpp_client_config_merge_buddies ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 3808 of file res_xmpp.c.

3809{
3810 struct ast_xmpp_buddy *buddy1 = obj, *buddy2;
3811 struct ao2_container *buddies = arg;
3812
3813 /* If the buddy does not already exist link it into the client buddies container */
3814 if (!(buddy2 = ao2_find(buddies, buddy1->id, OBJ_KEY))) {
3815 ao2_link(buddies, buddy1);
3816 } else {
3817 ao2_ref(buddy2, -1);
3818 }
3819
3820 /* All buddies are unlinked from the configuration buddies container, always */
3821 return 1;
3822}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
Generic container type.

References ao2_find, ao2_link, ao2_ref, ast_xmpp_buddy::id, and OBJ_KEY.

Referenced by xmpp_client_config_post_apply().

◆ xmpp_client_config_post_apply()

static int xmpp_client_config_post_apply ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 3863 of file res_xmpp.c.

3864{
3865 struct ast_xmpp_client_config *cfg = obj;
3867
3868 /* Merge global options that have not been modified */
3869 ast_copy_flags(&cfg->flags, &gcfg->global->general, ~(cfg->mod_flags.flags) & (XMPP_AUTOPRUNE | XMPP_AUTOREGISTER | XMPP_AUTOACCEPT));
3870
3871 /* Merge buddies as need be */
3873
3874 if (cfg->client->reconnect) {
3875 /* Disconnect the existing session since our role is changing, or we are starting up */
3877
3878 if (!(cfg->client->parser = iks_stream_new(ast_test_flag(&cfg->flags, XMPP_COMPONENT) ? "jabber:component:accept" : "jabber:client", cfg->client,
3879 xmpp_action_hook))) {
3880 ast_log(LOG_ERROR, "Iksemel stream could not be created for client '%s' - client not active\n", cfg->name);
3881 return -1;
3882 }
3883
3884 iks_set_log_hook(cfg->client->parser, xmpp_log_hook);
3885
3886 /* Create a JID based on the given user, if no resource is given use the default */
3887 if (!strchr(cfg->user, '/') && !ast_test_flag(&cfg->flags, XMPP_COMPONENT)) {
3888 char resource[strlen(cfg->user) + strlen("/asterisk-xmpp") + 1];
3889
3890 snprintf(resource, sizeof(resource), "%s/asterisk-xmpp", cfg->user);
3891 cfg->client->jid = iks_id_new(cfg->client->stack, resource);
3892 } else {
3893 cfg->client->jid = iks_id_new(cfg->client->stack, cfg->user);
3894 }
3895
3896 if (!cfg->client->jid || (ast_strlen_zero(cfg->client->jid->user) && !ast_test_flag(&cfg->flags, XMPP_COMPONENT))) {
3897 ast_log(LOG_ERROR, "Jabber identity '%s' could not be created for client '%s' - client not active\n", cfg->user, cfg->name);
3898 return -1;
3899 }
3900
3902
3903 cfg->client->reconnect = 0;
3904 } else if (cfg->client->state == XMPP_STATE_CONNECTED) {
3905 /* If this client is connected update their presence status since it may have changed */
3906 xmpp_client_set_presence(cfg->client, NULL, cfg->client->jid->full, cfg->status, cfg->statusmsg);
3907
3908 /* Subscribe to the status of any newly added buddies */
3911 }
3912 }
3913
3914 return 0;
3915}
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
static int xmpp_client_config_merge_buddies(void *obj, void *arg, int flags)
Definition: res_xmpp.c:3808
static void xmpp_client_set_presence(struct ast_xmpp_client *client, const char *to, const char *from, int level, const char *desc)
Internal function which changes the presence status of an XMPP client.
Definition: res_xmpp.c:2305
int ast_xmpp_client_disconnect(struct ast_xmpp_client *client)
Disconnect an XMPP client connection.
Definition: res_xmpp.c:3525
static void * xmpp_client_thread(void *data)
XMPP client connection thread.
Definition: res_xmpp.c:3728
static int xmpp_client_subscribe_user(void *obj, void *arg, int flags)
Callback function which subscribes to a user if needed.
Definition: res_xmpp.c:2226
static int xmpp_action_hook(void *data, int type, iks *node)
Action hook for when things occur.
Definition: res_xmpp.c:3455
static void xmpp_log_hook(void *data, const char *xmpp, size_t size, int incoming)
Logging hook function.
Definition: res_xmpp.c:2471
unsigned int flags
Definition: utils.h:200
const ast_string_field user
Definition: res_xmpp.c:462
const ast_string_field statusmsg
Definition: res_xmpp.c:462
unsigned int reconnect
Definition: xmpp.h:142
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, ast_copy_flags, ast_log, ast_pthread_create_background, ast_strlen_zero(), ast_test_flag, ast_xmpp_client_disconnect(), ast_xmpp_client::buddies, ast_xmpp_client_config::buddies, ast_xmpp_client_config::client, ast_flags::flags, ast_xmpp_client_config::flags, globals, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client_config::mod_flags, ast_xmpp_client_config::name, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_xmpp_client::parser, RAII_VAR, ast_xmpp_client::reconnect, ast_xmpp_client::stack, ast_xmpp_client::state, ast_xmpp_client_config::status, ast_xmpp_client_config::statusmsg, ast_xmpp_client::thread, ast_xmpp_client_config::user, xmpp_action_hook(), XMPP_AUTOACCEPT, XMPP_AUTOPRUNE, XMPP_AUTOREGISTER, xmpp_client_config_merge_buddies(), xmpp_client_set_presence(), xmpp_client_subscribe_user(), xmpp_client_thread(), XMPP_COMPONENT, xmpp_log_hook(), and XMPP_STATE_CONNECTED.

Referenced by xmpp_config_post_apply().

◆ xmpp_client_create_buddy()

static struct ast_xmpp_buddy * xmpp_client_create_buddy ( struct ao2_container container,
const char *  id 
)
static

Internal function which creates a buddy on a client.

Definition at line 2163 of file res_xmpp.c.

2164{
2165 struct ast_xmpp_buddy *buddy;
2166
2167 if (!(buddy = ao2_alloc(sizeof(*buddy), xmpp_buddy_destructor))) {
2168 return NULL;
2169 }
2170
2173 if (!buddy->resources) {
2174 ao2_ref(buddy, -1);
2175 return NULL;
2176 }
2177
2178 ast_copy_string(buddy->id, id, sizeof(buddy->id));
2179
2180 /* Assume we need to subscribe to get their presence until proven otherwise */
2181 buddy->subscribe = 1;
2182
2183 ao2_link(container, buddy);
2184
2185 return buddy;
2186}
struct ao2_container * container
Definition: res_fax.c:501
#define RESOURCE_BUCKETS
Number of buckets for resources (per buddy)
Definition: res_xmpp.c:432
static int xmpp_resource_hash(const void *obj, const int flags)
Hashing function for XMPP resource.
Definition: res_xmpp.c:845
static void xmpp_buddy_destructor(void *obj)
Destructor callback function for XMPP buddy.
Definition: res_xmpp.c:862
unsigned int subscribe
Definition: xmpp.h:115

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_link, ao2_ref, ast_copy_string(), container, ast_xmpp_buddy::id, NULL, RESOURCE_BUCKETS, ast_xmpp_buddy::resources, ast_xmpp_buddy::subscribe, xmpp_buddy_destructor(), xmpp_resource_cmp(), and xmpp_resource_hash().

Referenced by client_buddy_handler(), xmpp_pak_s10n(), and xmpp_roster_hook().

◆ xmpp_client_destructor()

static void xmpp_client_destructor ( void *  obj)
static

Destructor callback function for XMPP client.

Definition at line 551 of file res_xmpp.c.

552{
553 struct ast_xmpp_client *client = obj;
555
557
559 client->endpoint = NULL;
560
561 if (client->filter) {
562 iks_filter_delete(client->filter);
563 }
564
565 if (client->stack) {
566 iks_stack_delete(client->stack);
567 }
568
569 ao2_cleanup(client->buddies);
570
571 while ((message = AST_LIST_REMOVE_HEAD(&client->messages, list))) {
573 }
575}
void ast_endpoint_shutdown(struct ast_endpoint *endpoint)
Shutsdown an ast_endpoint.
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:653
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833

References ao2_cleanup, ast_endpoint_shutdown(), AST_LIST_HEAD_DESTROY, AST_LIST_REMOVE_HEAD, ast_xmpp_client_disconnect(), ast_xmpp_client::buddies, ast_xmpp_client::endpoint, ast_xmpp_client::filter, ast_xmpp_message::list, ast_xmpp_message::message, ast_xmpp_client::messages, NULL, ast_xmpp_client::stack, and xmpp_message_destroy().

Referenced by xmpp_client_alloc().

◆ xmpp_client_find_or_create()

static void * xmpp_client_find_or_create ( const char *  category)
static

Look up existing client or create a new one.

Definition at line 663 of file res_xmpp.c.

664{
666 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
667
668 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, category))) {
669 return xmpp_client_alloc(category);
670 }
671
672 ao2_ref(clientcfg->client, +1);
673 return clientcfg->client;
674}
static struct ast_xmpp_client * xmpp_client_alloc(const char *name)
Allocator function for ast_xmpp_client.
Definition: res_xmpp.c:610

References ao2_cleanup, ao2_global_obj_ref, ao2_ref, globals, NULL, RAII_VAR, xmpp_client_alloc(), and xmpp_config_find().

Referenced by ast_xmpp_client_config_alloc().

◆ xmpp_client_receive()

static int xmpp_client_receive ( struct ast_xmpp_client client,
unsigned int  timeout 
)
static

Internal function which receives data from the XMPP client connection.

Definition at line 3648 of file res_xmpp.c.

3649{
3650 int len, ret, pos = 0, newbufpos = 0;
3651 char buf[NET_IO_BUF_SIZE - 1] = "";
3652 char newbuf[NET_IO_BUF_SIZE - 1] = "";
3653 unsigned char c;
3654
3655 while (1) {
3656 len = xmpp_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout);
3657 if (len < 0) return IKS_NET_RWERR;
3658 if (len == 0) return IKS_NET_EXPIRED;
3659 buf[len] = '\0';
3660
3661 /* our iksemel parser won't work as expected if we feed
3662 it with XML packets that contain multiple whitespace
3663 characters between tags */
3664 while (pos < len) {
3665 c = buf[pos];
3666 /* if we stumble on the ending tag character,
3667 we skip any whitespace that follows it*/
3668 if (c == '>') {
3669 while (isspace(buf[pos+1])) {
3670 pos++;
3671 }
3672 }
3673 newbuf[newbufpos] = c;
3674 newbufpos++;
3675 pos++;
3676 }
3677 pos = 0;
3678 newbufpos = 0;
3679
3680 /* Log the message here, because iksemel's logHook is
3681 unaccessible */
3682 xmpp_log_hook(client, buf, len, 1);
3683
3684 if(buf[0] == ' ') {
3685 ast_debug(1, "JABBER: Detected Google Keep Alive. "
3686 "Sending out Ping request for client '%s'\n", client->name);
3687 /* If we just send out the ping here then we will have socket
3688 * read errors because the socket will timeout */
3689 xmpp_ping_request(client, client->jid->server, client->jid->full);
3690 }
3691
3692 /* let iksemel deal with the string length,
3693 and reset our buffer */
3694 ret = iks_parse(client->parser, newbuf, 0, 0);
3695 memset(newbuf, 0, sizeof(newbuf));
3696
3697 switch (ret) {
3698 case IKS_NOMEM:
3699 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n");
3700 break;
3701 case IKS_BADXML:
3702 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n");
3703 break;
3704 case IKS_HOOK:
3705 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n");
3706 break;
3707 }
3708 if (ret != IKS_OK) {
3709 return ret;
3710 }
3711 ast_debug(3, "XML parsing successful\n");
3712 }
3713 return IKS_OK;
3714}
static BUFHEAD * newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp)
Definition: hash_buf.c:160
static int xmpp_ping_request(struct ast_xmpp_client *client, const char *to, const char *from)
Helper function which sends a ping request to a server.
Definition: res_xmpp.c:3229
static int xmpp_io_recv(struct ast_xmpp_client *client, char *buffer, size_t buf_len, int timeout)
Internal function which polls on an XMPP client and receives data.
Definition: res_xmpp.c:3614
static struct test_val c
#define NET_IO_BUF_SIZE
Definition: xmpp.h:38
#define IKS_NET_EXPIRED
Definition: xmpp.h:41

References ast_debug, ast_log, buf, c, IKS_NET_EXPIRED, ast_xmpp_client::jid, len(), LOG_WARNING, ast_xmpp_client::name, NET_IO_BUF_SIZE, newbuf(), ast_xmpp_client::parser, xmpp_io_recv(), xmpp_log_hook(), and xmpp_ping_request().

Referenced by xmpp_client_thread().

◆ xmpp_client_reconnect()

static int xmpp_client_reconnect ( struct ast_xmpp_client client)
static

Internal function used to reconnect an XMPP client to its server.

Definition at line 3564 of file res_xmpp.c.

3565{
3566 struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
3568 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3569 int res = IKS_NET_NOCONN;
3570
3571 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
3572 return -1;
3573 }
3574
3576
3577 client->timeout = 50;
3578 iks_parser_reset(client->parser);
3579
3580 if (!client->filter && !(client->filter = iks_filter_new())) {
3581 ast_log(LOG_ERROR, "Could not create IKS filter for client connection '%s'\n", client->name);
3582 return -1;
3583 }
3584
3585 if (!ast_strlen_zero(clientcfg->refresh_token)) {
3586 ast_debug(2, "Obtaining OAuth access token for client '%s'\n", client->name);
3587 if (fetch_access_token(clientcfg)) {
3588 return -1;
3589 }
3590 }
3591
3592 /* If it's a component connect to user otherwise connect to server */
3593 res = iks_connect_via(client->parser, S_OR(clientcfg->server, client->jid->server), clientcfg->port,
3594 ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) ? clientcfg->user : client->jid->server);
3595
3596 /* Set socket timeout options */
3597 setsockopt(iks_fd(client->parser), SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
3598
3599 if (res == IKS_NET_NOCONN) {
3600 ast_log(LOG_ERROR, "No XMPP connection available when trying to connect client '%s'\n", client->name);
3601 return -1;
3602 } else if (res == IKS_NET_NODNS) {
3603 ast_log(LOG_ERROR, "No DNS available for XMPP connection when trying to connect client '%s'\n", client->name);
3604 return -1;
3605 }
3606
3607 /* Depending on the configuration of the client we eiher jump to requesting TLS, or authenticating */
3609
3610 return 0;
3611}
static int fetch_access_token(struct ast_xmpp_client_config *cfg)
Definition: res_xmpp.c:3824
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
@ XMPP_STATE_AUTHENTICATE
Definition: xmpp.h:77
@ XMPP_STATE_REQUEST_TLS
Definition: xmpp.h:75

References ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_log, ast_strlen_zero(), ast_test_flag, ast_xmpp_client_disconnect(), fetch_access_token(), ast_xmpp_client::filter, globals, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::name, NULL, ast_xmpp_client::parser, RAII_VAR, S_OR, ast_xmpp_client::timeout, xmpp_client_change_state(), XMPP_COMPONENT, xmpp_config_find(), XMPP_STATE_AUTHENTICATE, XMPP_STATE_REQUEST_TLS, and XMPP_USETLS.

Referenced by xmpp_client_thread().

◆ xmpp_client_request_tls()

static int xmpp_client_request_tls ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we need to request TLS support.

Definition at line 2540 of file res_xmpp.c.

2541{
2542 /* If the client connection is already secure we can jump straight to authenticating */
2543 if (xmpp_is_secure(client)) {
2545 return 0;
2546 }
2547
2548#ifndef HAVE_OPENSSL
2549 ast_log(LOG_ERROR, "TLS connection for client '%s' cannot be established. OpenSSL is not available.\n", client->name);
2550 return -1;
2551#else
2552 if (iks_send_raw(client->parser, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>") == IKS_NET_TLSFAIL) {
2553 ast_log(LOG_ERROR, "TLS connection for client '%s' cannot be started.\n", client->name);
2554 return -1;
2555 }
2556
2557 client->stream_flags |= TRY_SECURE;
2558
2560
2561 return 0;
2562#endif
2563}
@ XMPP_STATE_REQUESTED_TLS
Definition: xmpp.h:76

References ast_log, LOG_ERROR, ast_xmpp_client::name, ast_xmpp_client::parser, xmpp_client_change_state(), xmpp_is_secure(), XMPP_STATE_AUTHENTICATE, and XMPP_STATE_REQUESTED_TLS.

◆ xmpp_client_requested_tls()

static int xmpp_client_requested_tls ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we receive a response to our TLS initiation request.

Definition at line 2584 of file res_xmpp.c.

2585{
2586#ifdef HAVE_OPENSSL
2587 int sock;
2588 long ssl_opts;
2589 char *err;
2590#endif
2591
2592 if (!strcmp(iks_name(node), "success")) {
2593 /* TLS is up and working, we can move on to authenticating now */
2595 return 0;
2596 } else if (!strcmp(iks_name(node), "failure")) {
2597 /* TLS negotiation was a failure, close it on down! */
2598 return -1;
2599 } else if (strcmp(iks_name(node), "proceed")) {
2600 /* Ignore any other responses */
2601 return 0;
2602 }
2603
2604#ifndef HAVE_OPENSSL
2605 ast_log(LOG_ERROR, "Somehow we managed to try to start TLS negotiation on client '%s' without OpenSSL support, disconnecting\n", client->name);
2606 return -1;
2607#else
2608 client->ssl_method = SSLv23_method();
2609 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) {
2610 goto failure;
2611 }
2612
2613 ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
2614 SSL_CTX_set_options(client->ssl_context, ssl_opts);
2615
2616 if (!(client->ssl_session = SSL_new(client->ssl_context))) {
2617 goto failure;
2618 }
2619
2620 sock = iks_fd(client->parser);
2621 if (!SSL_set_fd(client->ssl_session, sock)) {
2622 goto failure;
2623 }
2624
2625 if (SSL_connect(client->ssl_session) <= 0) {
2626 goto failure;
2627 }
2628
2629 client->stream_flags &= (~TRY_SECURE);
2630 client->stream_flags |= SECURE;
2631
2632 if (xmpp_send_stream_header(client, cfg, client->jid->server) != IKS_OK) {
2633 ast_log(LOG_ERROR, "TLS connection for client '%s' could not be established, failed to send stream header after negotiation\n",
2634 client->name);
2635 return -1;
2636 }
2637
2638 ast_debug(1, "TLS connection for client '%s' started with server\n", client->name);
2639
2641
2642 return 0;
2643
2644failure:
2645 err = openssl_error_string();
2646 ast_log(LOG_ERROR, "TLS connection for client '%s' cannot be established. "
2647 "OpenSSL initialization failed: %s\n", client->name, err);
2648 ast_free(err);
2649 return -1;
2650#endif
2651}

References ast_debug, ast_free, ast_log, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::name, ast_xmpp_client::parser, xmpp_client_change_state(), xmpp_send_stream_header(), and XMPP_STATE_AUTHENTICATE.

◆ xmpp_client_send_disco_info_request()

static int xmpp_client_send_disco_info_request ( struct ast_xmpp_client client,
const char *  to,
const char *  from 
)
static

Helper function which sends a discovery information request to a user.

Definition at line 3192 of file res_xmpp.c.

3193{
3194 iks *iq, *query;
3195 int res;
3196
3197 if (!(iq = iks_new("iq")) || !(query = iks_new("query"))) {
3198 iks_delete(iq);
3199 return -1;
3200 }
3201
3202 iks_insert_attrib(iq, "type", "get");
3203 iks_insert_attrib(iq, "to", to);
3204 iks_insert_attrib(iq, "from", from);
3205 ast_xmpp_client_lock(client);
3206 iks_insert_attrib(iq, "id", client->mid);
3207 ast_xmpp_increment_mid(client->mid);
3208 ast_xmpp_client_unlock(client);
3209 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
3210 iks_insert_node(iq, query);
3211
3212 res = ast_xmpp_client_send(client, iq);
3213
3214 iks_delete(query);
3215 iks_delete(iq);
3216
3217 return res;
3218}

References ast_xmpp_client_lock(), ast_xmpp_client_send(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), and ast_xmpp_client::mid.

Referenced by xmpp_pak_presence().

◆ xmpp_client_send_message()

static int xmpp_client_send_message ( struct ast_xmpp_client client,
int  group,
const char *  nick,
const char *  address,
const char *  message 
)
static

Internal function used to send a message to a user or chatroom.

Definition at line 910 of file res_xmpp.c.

911{
913 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
914 int res = 0;
915 char from[XMPP_MAX_JIDLEN];
916 iks *message_packet;
917
918 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
919 !(message_packet = iks_make_msg(group ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message))) {
920 return -1;
921 }
922
923 if (!ast_strlen_zero(nick) && ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
924 snprintf(from, sizeof(from), "%s@%s/%s", nick, client->jid->full, nick);
925 } else {
926 snprintf(from, sizeof(from), "%s", client->jid->full);
927 }
928
929 iks_insert_attrib(message_packet, "from", from);
930
931 res = ast_xmpp_client_send(client, message_packet);
932
933 iks_delete(message_packet);
934
935 return res;
936}

References ao2_cleanup, ao2_global_obj_ref, ast_strlen_zero(), ast_test_flag, ast_xmpp_client_send(), globals, ast_xmpp_client::jid, ast_xmpp_client::name, NULL, RAII_VAR, XMPP_COMPONENT, xmpp_config_find(), and XMPP_MAX_JIDLEN.

Referenced by ast_xmpp_chatroom_send(), and ast_xmpp_client_send_message().

◆ xmpp_client_send_raw_message()

static int xmpp_client_send_raw_message ( struct ast_xmpp_client client,
const char *  message 
)
static

Internal function which sends a raw message.

Definition at line 2489 of file res_xmpp.c.

2490{
2491 int ret;
2492
2493 if (client->state == XMPP_STATE_DISCONNECTED) {
2494 /* iks_send_raw will crash without a connection */
2495 return IKS_NET_NOCONN;
2496 }
2497
2498#ifdef HAVE_OPENSSL
2499 if (xmpp_is_secure(client)) {
2500 int len = strlen(message);
2501
2502 ret = SSL_write(client->ssl_session, message, len);
2503 if (ret) {
2504 /* Log the message here, because iksemel's logHook is
2505 unaccessible */
2506 xmpp_log_hook(client, message, len, 0);
2507 return IKS_OK;
2508 }
2509 }
2510#endif
2511 /* If needed, data will be sent unencrypted, and logHook will
2512 be called inside iks_send_raw */
2513 ret = iks_send_raw(client->parser, message);
2514 if (ret != IKS_OK) {
2515 return ret;
2516 }
2517
2518 return IKS_OK;
2519}

References len(), ast_xmpp_client::parser, ast_xmpp_client::state, xmpp_is_secure(), xmpp_log_hook(), and XMPP_STATE_DISCONNECTED.

Referenced by ast_xmpp_client_send(), xmpp_component_authenticate(), and xmpp_send_stream_header().

◆ xmpp_client_service_discovery_get_hook()

static int xmpp_client_service_discovery_get_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when client receives a service discovery get message.

Definition at line 2343 of file res_xmpp.c.

2344{
2345 struct ast_xmpp_client *client = data;
2346 iks *iq, *disco = NULL, *ident = NULL, *google = NULL, *jingle = NULL, *ice = NULL, *rtp = NULL, *audio = NULL, *video = NULL, *query = NULL;
2347
2348 if (!(iq = iks_new("iq")) || !(query = iks_new("query")) || !(ident = iks_new("identity")) || !(disco = iks_new("feature")) ||
2349 !(google = iks_new("feature")) || !(jingle = iks_new("feature")) || !(ice = iks_new("feature")) || !(rtp = iks_new("feature")) ||
2350 !(audio = iks_new("feature")) || !(video = iks_new("feature"))) {
2351 ast_log(LOG_ERROR, "Could not allocate memory for responding to service discovery request from '%s' on client '%s'\n",
2352 pak->from->full, client->name);
2353 goto end;
2354 }
2355
2356 iks_insert_attrib(iq, "from", client->jid->full);
2357
2358 if (pak->from) {
2359 iks_insert_attrib(iq, "to", pak->from->full);
2360 }
2361
2362 iks_insert_attrib(iq, "type", "result");
2363 iks_insert_attrib(iq, "id", pak->id);
2364 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
2365 iks_insert_attrib(ident, "category", "client");
2366 iks_insert_attrib(ident, "type", "pc");
2367 iks_insert_attrib(ident, "name", "asterisk");
2368 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
2369
2370 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
2371 iks_insert_attrib(jingle, "var", "urn:xmpp:jingle:1");
2372 iks_insert_attrib(ice, "var", "urn:xmpp:jingle:transports:ice-udp:1");
2373 iks_insert_attrib(rtp, "var", "urn:xmpp:jingle:apps:rtp:1");
2374 iks_insert_attrib(audio, "var", "urn:xmpp:jingle:apps:rtp:audio");
2375 iks_insert_attrib(video, "var", "urn:xmpp:jingle:apps:rtp:video");
2376 iks_insert_node(iq, query);
2377 iks_insert_node(query, ident);
2378 iks_insert_node(query, google);
2379 iks_insert_node(query, disco);
2380 iks_insert_node(query, jingle);
2381 iks_insert_node(query, ice);
2382 iks_insert_node(query, rtp);
2383 iks_insert_node(query, audio);
2384 iks_insert_node(query, video);
2385 ast_xmpp_client_send(client, iq);
2386
2387end:
2388 iks_delete(query);
2389 iks_delete(video);
2390 iks_delete(audio);
2391 iks_delete(rtp);
2392 iks_delete(ice);
2393 iks_delete(jingle);
2394 iks_delete(google);
2395 iks_delete(ident);
2396 iks_delete(disco);
2397 iks_delete(iq);
2398
2399 return IKS_FILTER_EAT;
2400}
char * end
Definition: eagi_proxy.c:73

References ast_log, ast_xmpp_client_send(), end, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::name, and NULL.

Referenced by xmpp_connect_hook().

◆ xmpp_client_service_discovery_result_hook()

static int xmpp_client_service_discovery_result_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when client receives a service discovery result message.

Definition at line 2403 of file res_xmpp.c.

2404{
2405 struct ast_xmpp_client *client = data;
2406 struct ast_xmpp_buddy *buddy;
2408
2409 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY))) {
2410 return IKS_FILTER_EAT;
2411 }
2412
2413 if (!(resource = ao2_callback(buddy->resources, 0, xmpp_resource_cmp, pak->from->resource))) {
2414 ao2_ref(buddy, -1);
2415 return IKS_FILTER_EAT;
2416 }
2417
2419
2420 if (iks_find_with_attrib(pak->query, "feature", "var", "urn:xmpp:jingle:1")) {
2421 resource->caps.jingle = 1;
2422 }
2423
2425
2426 ao2_ref(resource, -1);
2427 ao2_ref(buddy, -1);
2428
2429 return IKS_FILTER_EAT;
2430}
char resource[XMPP_MAX_RESJIDLEN]
Definition: xmpp.h:93

References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_xmpp_client::buddies, OBJ_KEY, ast_xmpp_resource::resource, ast_xmpp_buddy::resources, and xmpp_resource_cmp().

Referenced by xmpp_component_authenticating(), and xmpp_connect_hook().

◆ xmpp_client_set_group_presence()

static int xmpp_client_set_group_presence ( struct ast_xmpp_client client,
const char *  room,
int  level,
const char *  nick 
)
static

Definition at line 974 of file res_xmpp.c.

975{
977 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
978 int res = 0;
979 iks *presence = NULL, *x = NULL;
980 char from[XMPP_MAX_JIDLEN], roomid[XMPP_MAX_JIDLEN];
981
982 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
983 !(presence = iks_make_pres(level, NULL)) || !(x = iks_new("x"))) {
984 res = -1;
985 goto done;
986 }
987
988 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
989 snprintf(from, sizeof(from), "%s@%s/%s", nick, client->jid->full, nick);
990 snprintf(roomid, sizeof(roomid), "%s/%s", room, nick);
991 } else {
992 snprintf(from, sizeof(from), "%s", client->jid->full);
993 snprintf(roomid, sizeof(roomid), "%s/%s", room, S_OR(nick, client->jid->user));
994 }
995
996 iks_insert_attrib(presence, "to", roomid);
997 iks_insert_attrib(presence, "from", from);
998 iks_insert_attrib(x, "xmlns", "http://jabber.org/protocol/muc");
999 iks_insert_node(presence, x);
1000
1001 res = ast_xmpp_client_send(client, presence);
1002
1003done:
1004 iks_delete(x);
1005 iks_delete(presence);
1006
1007 return res;
1008}

References ao2_cleanup, ao2_global_obj_ref, ast_test_flag, ast_xmpp_client_send(), done, globals, ast_xmpp_client::jid, ast_xmpp_client::name, NULL, RAII_VAR, S_OR, XMPP_COMPONENT, xmpp_config_find(), and XMPP_MAX_JIDLEN.

Referenced by ast_xmpp_chatroom_join(), and ast_xmpp_chatroom_leave().

◆ xmpp_client_set_presence()

static void xmpp_client_set_presence ( struct ast_xmpp_client client,
const char *  to,
const char *  from,
int  level,
const char *  desc 
)
static

Internal function which changes the presence status of an XMPP client.

Definition at line 2305 of file res_xmpp.c.

2306{
2308 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2309 iks *presence = NULL, *cnode = NULL, *priority = NULL;
2310 char priorityS[10];
2311
2312 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
2313 !(presence = iks_make_pres(level, desc)) || !(cnode = iks_new("c")) || !(priority = iks_new("priority"))) {
2314 ast_log(LOG_ERROR, "Unable to allocate stanzas for setting presence status for client '%s'\n", client->name);
2315 goto done;
2316 }
2317
2318 if (!ast_strlen_zero(to)) {
2319 iks_insert_attrib(presence, "to", to);
2320 }
2321
2322 if (!ast_strlen_zero(from)) {
2323 iks_insert_attrib(presence, "from", from);
2324 }
2325
2326 snprintf(priorityS, sizeof(priorityS), "%d", clientcfg->priority);
2327 iks_insert_cdata(priority, priorityS, strlen(priorityS));
2328 iks_insert_node(presence, priority);
2329 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
2330 iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
2331 iks_insert_attrib(cnode, "ext", "voice-v1 video-v1 camera-v1");
2332 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
2333 iks_insert_node(presence, cnode);
2334 ast_xmpp_client_send(client, presence);
2335
2336done:
2337 iks_delete(cnode);
2338 iks_delete(presence);
2339 iks_delete(priority);
2340}
static const char desc[]
Definition: cdr_radius.c:84

References ao2_cleanup, ao2_global_obj_ref, ast_log, ast_strlen_zero(), ast_xmpp_client_send(), desc, done, globals, LOG_ERROR, ast_xmpp_client::name, NULL, priority, RAII_VAR, and xmpp_config_find().

Referenced by xmpp_client_config_post_apply(), xmpp_connect_hook(), xmpp_pak_presence(), and xmpp_pak_s10n().

◆ xmpp_client_subscribe_user()

static int xmpp_client_subscribe_user ( void *  obj,
void *  arg,
int  flags 
)
static

Callback function which subscribes to a user if needed.

Definition at line 2226 of file res_xmpp.c.

2227{
2228 struct ast_xmpp_buddy *buddy = obj;
2229 struct ast_xmpp_client *client = arg;
2230
2231 if (!buddy->subscribe) {
2232 return 0;
2233 }
2234
2235 if (ast_xmpp_client_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, buddy->id,
2236 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"))) {
2237 ast_log(LOG_WARNING, "Could not send subscription for '%s' on client '%s'\n",
2238 buddy->id, client->name);
2239 }
2240
2241 buddy->subscribe = 0;
2242
2243 return 0;
2244}

References ast_log, ast_xmpp_client_send(), ast_xmpp_buddy::id, LOG_WARNING, ast_xmpp_client::name, and ast_xmpp_buddy::subscribe.

Referenced by xmpp_client_config_post_apply(), and xmpp_roster_hook().

◆ xmpp_client_thread()

static void * xmpp_client_thread ( void *  data)
static

XMPP client connection thread.

Definition at line 3728 of file res_xmpp.c.

3729{
3730 struct ast_xmpp_client *client = data;
3731 int res = IKS_NET_RWERR;
3732 unsigned int sleep_time = 1;
3733
3734 /* We only allow cancellation while sleeping */
3735 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
3736
3737 do {
3738 if (client->state == XMPP_STATE_DISCONNECTING) {
3739 ast_debug(1, "[%s] Disconnecting\n", client->name);
3740 break;
3741 }
3742
3743 if (res == IKS_NET_RWERR || client->timeout == 0) {
3744 ast_debug(3, "[%s] Connecting\n", client->name);
3745 if ((res = xmpp_client_reconnect(client)) != IKS_OK) {
3746 sleep_with_backoff(&sleep_time);
3747 res = IKS_NET_RWERR;
3748 }
3749 continue;
3750 }
3751
3752 res = xmpp_client_receive(client, 1);
3753
3754 /* Decrease timeout if no data received, and delete
3755 * old messages globally */
3756 if (res == IKS_NET_EXPIRED) {
3757 client->timeout--;
3758 }
3759
3760 if (res == IKS_HOOK) {
3761 ast_debug(2, "[%s] Got hook event\n", client->name);
3762 } else if (res == IKS_NET_TLSFAIL) {
3763 ast_log(LOG_ERROR, "[%s] TLS failure\n", client->name);
3764 } else if (!client->timeout && client->state == XMPP_STATE_CONNECTED) {
3766 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3767
3768 if (cfg && cfg->clients) {
3769 clientcfg = xmpp_config_find(cfg->clients, client->name);
3770 }
3771
3772 if (clientcfg && ast_test_flag(&clientcfg->flags, XMPP_KEEPALIVE)) {
3773 res = xmpp_ping_request(client, client->jid->server, client->jid->full);
3774 } else {
3775 res = IKS_OK;
3776 }
3777
3778 if (res == IKS_OK) {
3779 client->timeout = 50;
3780 } else {
3781 ast_log(LOG_WARNING, "[%s] Network timeout\n", client->name);
3782 }
3783 } else if (res == IKS_NET_RWERR) {
3784 ast_log(LOG_WARNING, "[%s] Socket read error\n", client->name);
3786 sleep_with_backoff(&sleep_time);
3787 } else if (res == IKS_NET_NOSOCK) {
3788 ast_log(LOG_WARNING, "[%s] No socket\n", client->name);
3789 } else if (res == IKS_NET_NOCONN) {
3790 ast_log(LOG_WARNING, "[%s] No connection\n", client->name);
3791 } else if (res == IKS_NET_NODNS) {
3792 ast_log(LOG_WARNING, "[%s] No DNS\n", client->name);
3793 } else if (res == IKS_NET_NOTSUPP) {
3794 ast_log(LOG_WARNING, "[%s] Not supported\n", client->name);
3795 } else if (res == IKS_NET_DROPPED) {
3796 ast_log(LOG_WARNING, "[%s] Dropped?\n", client->name);
3797 } else if (res == IKS_NET_UNKNOWN) {
3798 ast_debug(5, "[%s] Unknown\n", client->name);
3799 } else if (res == IKS_OK) {
3800 sleep_time = 1;
3801 }
3802
3803 } while (1);
3804
3805 return NULL;
3806}
static int xmpp_client_reconnect(struct ast_xmpp_client *client)
Internal function used to reconnect an XMPP client to its server.
Definition: res_xmpp.c:3564
static void sleep_with_backoff(unsigned int *sleep_time)
Definition: res_xmpp.c:3716
static int xmpp_client_receive(struct ast_xmpp_client *client, unsigned int timeout)
Internal function which receives data from the XMPP client connection.
Definition: res_xmpp.c:3648

References ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_log, ast_test_flag, ast_xmpp_client_disconnect(), globals, IKS_NET_EXPIRED, ast_xmpp_client::jid, LOG_ERROR, LOG_WARNING, ast_xmpp_client::name, NULL, RAII_VAR, sleep_with_backoff(), ast_xmpp_client::state, ast_xmpp_client::timeout, xmpp_client_receive(), xmpp_client_reconnect(), xmpp_config_find(), XMPP_KEEPALIVE, xmpp_ping_request(), XMPP_STATE_CONNECTED, and XMPP_STATE_DISCONNECTING.

Referenced by xmpp_client_config_post_apply().

◆ xmpp_client_unsubscribe_user()

static int xmpp_client_unsubscribe_user ( struct ast_xmpp_client client,
const char *  user 
)
static

Helper function which unsubscribes a user and removes them from the roster.

Definition at line 2189 of file res_xmpp.c.

2190{
2191 iks *iq, *query = NULL, *item = NULL;
2192
2193 if (ast_xmpp_client_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, user,
2194 "Goodbye. Your status is no longer required.\n"))) {
2195 return -1;
2196 }
2197
2198 if (!(iq = iks_new("iq")) || !(query = iks_new("query")) || !(item = iks_new("item"))) {
2199 ast_log(LOG_WARNING, "Could not allocate memory for roster removal of '%s' from client '%s'\n",
2200 user, client->name);
2201 goto done;
2202 }
2203
2204 iks_insert_attrib(iq, "from", client->jid->full);
2205 iks_insert_attrib(iq, "type", "set");
2206 iks_insert_attrib(query, "xmlns", "jabber:iq:roster");
2207 iks_insert_node(iq, query);
2208 iks_insert_attrib(item, "jid", user);
2209 iks_insert_attrib(item, "subscription", "remove");
2210 iks_insert_node(query, item);
2211
2212 if (ast_xmpp_client_send(client, iq)) {
2213 ast_log(LOG_WARNING, "Could not send roster removal request of '%s' from client '%s'\n",
2214 user, client->name);
2215 }
2216
2217done:
2218 iks_delete(item);
2219 iks_delete(query);
2220 iks_delete(iq);
2221
2222 return 0;
2223}
static struct aco_type item
Definition: test_config.c:1463

References ast_log, ast_xmpp_client_send(), done, item, ast_xmpp_client::jid, LOG_WARNING, ast_xmpp_client::name, and NULL.

Referenced by xmpp_roster_hook().

◆ xmpp_component_authenticate()

static int xmpp_component_authenticate ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we should authenticate as a component.

Definition at line 2824 of file res_xmpp.c.

2825{
2826 char secret[160], shasum[320], message[344];
2827 ikspak *pak = iks_packet(node);
2828
2829 snprintf(secret, sizeof(secret), "%s%s", pak->id, cfg->password);
2830 ast_sha1_hash(shasum, secret);
2831 snprintf(message, sizeof(message), "<handshake>%s</handshake>", shasum);
2832
2833 if (xmpp_client_send_raw_message(client, message) != IKS_OK) {
2834 ast_log(LOG_ERROR, "Unable to send handshake for component '%s'\n", client->name);
2835 return -1;
2836 }
2837
2839
2840 return 0;
2841}

References ast_log, ast_sha1_hash(), LOG_ERROR, ast_xmpp_client::name, ast_xmpp_client_config::password, xmpp_client_change_state(), xmpp_client_send_raw_message(), and XMPP_STATE_AUTHENTICATING.

◆ xmpp_component_authenticating()

static int xmpp_component_authenticating ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
int  type,
iks *  node 
)
static

Internal function called when we authenticated as a component.

Definition at line 3090 of file res_xmpp.c.

3091{
3092 if (!strcmp(iks_name(node), "stream:features")) {
3093 return 0;
3094 }
3095
3096 if (strcmp(iks_name(node), "handshake")) {
3097 ast_log(LOG_ERROR, "Failed to authenticate component '%s'\n", client->name);
3098 return -1;
3099 }
3100
3101 iks_filter_add_rule(client->filter, xmpp_component_service_discovery_items_hook, client, IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
3102
3103 iks_filter_add_rule(client->filter, xmpp_component_service_discovery_get_hook, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
3104
3105 /* This uses the client service discovery result hook on purpose, as the code is common between both */
3106 iks_filter_add_rule(client->filter, xmpp_client_service_discovery_result_hook, client, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
3107
3108 iks_filter_add_rule(client->filter, xmpp_component_register_get_hook, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
3109 iks_filter_add_rule(client->filter, xmpp_component_register_set_hook, client, IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
3110
3112
3113 return 0;
3114}
static int xmpp_component_register_get_hook(void *data, ikspak *pak)
Hook function called when the component is queried about registration.
Definition: res_xmpp.c:2931
static int xmpp_client_service_discovery_result_hook(void *data, ikspak *pak)
Hook function called when client receives a service discovery result message.
Definition: res_xmpp.c:2403
static int xmpp_component_service_discovery_items_hook(void *data, ikspak *pak)
Hook function called when we receive a service discovery items request.
Definition: res_xmpp.c:3039
static int xmpp_component_service_discovery_get_hook(void *data, ikspak *pak)
Hook function called when component receives a service discovery get message.
Definition: res_xmpp.c:2844
static int xmpp_component_register_set_hook(void *data, ikspak *pak)
Hook function called when someone registers to the component.
Definition: res_xmpp.c:2992

References ast_log, ast_xmpp_client::filter, LOG_ERROR, ast_xmpp_client::name, xmpp_client_change_state(), xmpp_client_service_discovery_result_hook(), xmpp_component_register_get_hook(), xmpp_component_register_set_hook(), xmpp_component_service_discovery_get_hook(), xmpp_component_service_discovery_items_hook(), and XMPP_STATE_CONNECTED.

◆ xmpp_component_register_get_hook()

static int xmpp_component_register_get_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when the component is queried about registration.

Definition at line 2931 of file res_xmpp.c.

2932{
2934 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2935 struct ast_xmpp_client *client = data;
2936 iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL, *instructions = NULL;
2937 struct ast_xmpp_buddy *buddy;
2938 char *node;
2939
2940 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
2941 !(iq = iks_new("iq")) || !(query = iks_new("query")) || !(error = iks_new("error")) || !(notacceptable = iks_new("not-acceptable")) ||
2942 !(instructions = iks_new("instructions"))) {
2943 ast_log(LOG_ERROR, "Failed to allocate stanzas for register get response to '%s' on component '%s'\n",
2944 pak->from->partial, client->name);
2945 goto done;
2946 }
2947
2948 iks_insert_attrib(iq, "from", clientcfg->user);
2949 iks_insert_attrib(iq, "to", pak->from->full);
2950 iks_insert_attrib(iq, "id", pak->id);
2951 iks_insert_attrib(iq, "type", "result");
2952 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
2953 iks_insert_node(iq, query);
2954
2955 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY))) {
2956 iks_insert_attrib(error, "code", "406");
2957 iks_insert_attrib(error, "type", "modify");
2958 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
2959
2960 iks_insert_node(iq, error);
2961 iks_insert_node(error, notacceptable);
2962
2963 ast_log(LOG_ERROR, "Received register attempt from '%s' but buddy is not configured on component '%s'\n",
2964 pak->from->partial, client->name);
2965 } else if (!(node = iks_find_attrib(pak->query, "node"))) {
2966 iks_insert_cdata(instructions, "Welcome to Asterisk - the Open Source PBX.\n", 0);
2967 iks_insert_node(query, instructions);
2968 ao2_ref(buddy, -1);
2969 } else {
2970 ast_log(LOG_WARNING, "Received register get to component '%s' using unsupported node '%s' from '%s'\n",
2971 client->name, node, pak->from->partial);
2972 ao2_ref(buddy, -1);
2973 goto done;
2974 }
2975
2976 if (ast_xmpp_client_send(client, iq)) {
2977 ast_log(LOG_WARNING, "Could not send response to '%s' for received register get on component '%s'\n",
2978 pak->from->partial, client->name);
2979 }
2980
2981done:
2982 iks_delete(instructions);
2983 iks_delete(notacceptable);
2984 iks_delete(error);
2985 iks_delete(query);
2986 iks_delete(iq);
2987
2988 return IKS_FILTER_EAT;
2989}

References ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_ref, ast_log, ast_xmpp_client_send(), ast_xmpp_client::buddies, done, error(), globals, LOG_ERROR, LOG_WARNING, ast_xmpp_client::name, NULL, OBJ_KEY, RAII_VAR, and xmpp_config_find().

Referenced by xmpp_component_authenticating().

◆ xmpp_component_register_set_hook()

static int xmpp_component_register_set_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when someone registers to the component.

Definition at line 2992 of file res_xmpp.c.

2993{
2994 struct ast_xmpp_client *client = data;
2995 iks *iq, *presence = NULL, *x = NULL;
2996
2997 if (!(iq = iks_new("iq")) || !(presence = iks_new("presence")) || !(x = iks_new("x"))) {
2998 ast_log(LOG_ERROR, "Failed to allocate stanzas for register set response to '%s' on component '%s'\n",
2999 pak->from->partial, client->name);
3000 goto done;
3001 }
3002
3003 iks_insert_attrib(iq, "from", client->jid->full);
3004 iks_insert_attrib(iq, "to", pak->from->full);
3005 iks_insert_attrib(iq, "id", pak->id);
3006 iks_insert_attrib(iq, "type", "result");
3007
3008 if (ast_xmpp_client_send(client, iq)) {
3009 ast_log(LOG_WARNING, "Could not send response to '%s' for received register set on component '%s'\n",
3010 pak->from->partial, client->name);
3011 goto done;
3012 }
3013
3014 iks_insert_attrib(presence, "from", client->jid->full);
3015 iks_insert_attrib(presence, "to", pak->from->partial);
3016 ast_xmpp_client_lock(client);
3017 iks_insert_attrib(presence, "id", client->mid);
3018 ast_xmpp_increment_mid(client->mid);
3019 ast_xmpp_client_unlock(client);
3020 iks_insert_attrib(presence, "type", "subscribe");
3021 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
3022
3023 iks_insert_node(presence, x);
3024
3025 if (ast_xmpp_client_send(client, presence)) {
3026 ast_log(LOG_WARNING, "Could not send subscription to '%s' on component '%s'\n",
3027 pak->from->partial, client->name);
3028 }
3029
3030done:
3031 iks_delete(x);
3032 iks_delete(presence);
3033 iks_delete(iq);
3034
3035 return IKS_FILTER_EAT;
3036}

References ast_log, ast_xmpp_client_lock(), ast_xmpp_client_send(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), done, ast_xmpp_client::jid, LOG_ERROR, LOG_WARNING, ast_xmpp_client::mid, ast_xmpp_client::name, and NULL.

Referenced by xmpp_component_authenticating().

◆ xmpp_component_service_discovery_get_hook()

static int xmpp_component_service_discovery_get_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when component receives a service discovery get message.

Definition at line 2844 of file res_xmpp.c.

2845{
2847 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2848 struct ast_xmpp_client *client = data;
2849 iks *iq = NULL, *query = NULL, *identity = NULL, *disco = NULL, *reg = NULL, *commands = NULL, *gateway = NULL;
2850 iks *version = NULL, *vcard = NULL, *search = NULL, *item = NULL;
2851 char *node;
2852
2853 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
2854 !(iq = iks_new("iq")) || !(query = iks_new("query")) || !(identity = iks_new("identity")) || !(disco = iks_new("feature")) ||
2855 !(reg = iks_new("feature")) || !(commands = iks_new("feature")) || !(gateway = iks_new("feature")) || !(version = iks_new("feature")) ||
2856 !(vcard = iks_new("feature")) || !(search = iks_new("search")) || !(item = iks_new("item"))) {
2857 ast_log(LOG_ERROR, "Failed to allocate stanzas for service discovery get response to '%s' on component '%s'\n",
2858 pak->from->partial, client->name);
2859 goto done;
2860 }
2861
2862 iks_insert_attrib(iq, "from", clientcfg->user);
2863 iks_insert_attrib(iq, "to", pak->from->full);
2864 iks_insert_attrib(iq, "id", pak->id);
2865 iks_insert_attrib(iq, "type", "result");
2866
2867 if (!(node = iks_find_attrib(pak->query, "node"))) {
2868 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
2869 iks_insert_attrib(identity, "category", "gateway");
2870 iks_insert_attrib(identity, "type", "pstn");
2871 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX");
2872 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco");
2873 iks_insert_attrib(reg, "var", "jabber:iq:register");
2874 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
2875 iks_insert_attrib(gateway, "var", "jabber:iq:gateway");
2876 iks_insert_attrib(version, "var", "jabber:iq:version");
2877 iks_insert_attrib(vcard, "var", "vcard-temp");
2878 iks_insert_attrib(search, "var", "jabber:iq:search");
2879
2880 iks_insert_node(iq, query);
2881 iks_insert_node(query, identity);
2882 iks_insert_node(query, disco);
2883 iks_insert_node(query, reg);
2884 iks_insert_node(query, commands);
2885 iks_insert_node(query, gateway);
2886 iks_insert_node(query, version);
2887 iks_insert_node(query, vcard);
2888 iks_insert_node(query, search);
2889 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
2890 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
2891 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
2892 iks_insert_attrib(item, "node", "confirmaccount");
2893 iks_insert_attrib(item, "name", "Confirm account");
2894 iks_insert_attrib(item, "jid", clientcfg->user);
2895
2896 iks_insert_node(iq, query);
2897 iks_insert_node(query, item);
2898 } else if (!strcasecmp(node, "confirmaccount")) {
2899 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
2900 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
2901
2902 iks_insert_node(iq, query);
2903 iks_insert_node(query, commands);
2904 } else {
2905 ast_debug(3, "Unsupported service discovery info request received with node '%s' on component '%s'\n",
2906 node, client->name);
2907 goto done;
2908 }
2909
2910 if (ast_xmpp_client_send(client, iq)) {
2911 ast_log(LOG_WARNING, "Could not send response to service discovery request on component '%s'\n",
2912 client->name);
2913 }
2914
2915done:
2916 iks_delete(search);
2917 iks_delete(vcard);
2918 iks_delete(version);
2919 iks_delete(gateway);
2920 iks_delete(commands);
2921 iks_delete(reg);
2922 iks_delete(disco);
2923 iks_delete(identity);
2924 iks_delete(query);
2925 iks_delete(iq);
2926
2927 return IKS_FILTER_EAT;
2928}
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3738

References ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_log, ast_xmpp_client_send(), commands, done, globals, item, LOG_ERROR, LOG_WARNING, ast_xmpp_client::name, NULL, RAII_VAR, version, and xmpp_config_find().

Referenced by xmpp_component_authenticating().

◆ xmpp_component_service_discovery_items_hook()

static int xmpp_component_service_discovery_items_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when we receive a service discovery items request.

Definition at line 3039 of file res_xmpp.c.

3040{
3042 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3043 struct ast_xmpp_client *client = data;
3044 iks *iq = NULL, *query = NULL, *item = NULL, *feature = NULL;
3045 char *node;
3046
3047 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
3048 !(iq = iks_new("iq")) || !(query = iks_new("query")) || !(item = iks_new("item")) || !(feature = iks_new("feature"))) {
3049 ast_log(LOG_ERROR, "Failed to allocate stanzas for service discovery items response to '%s' on component '%s'\n",
3050 pak->from->partial, client->name);
3051 goto done;
3052 }
3053
3054 iks_insert_attrib(iq, "from", clientcfg->user);
3055 iks_insert_attrib(iq, "to", pak->from->full);
3056 iks_insert_attrib(iq, "id", pak->id);
3057 iks_insert_attrib(iq, "type", "result");
3058 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
3059 iks_insert_node(iq, query);
3060
3061 if (!(node = iks_find_attrib(pak->query, "node"))) {
3062 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
3063 iks_insert_attrib(item, "name", "Asterisk Commands");
3064 iks_insert_attrib(item, "jid", clientcfg->user);
3065
3066 iks_insert_node(query, item);
3067 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
3068 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
3069 } else {
3070 ast_log(LOG_WARNING, "Received service discovery items request to component '%s' using unsupported node '%s' from '%s'\n",
3071 client->name, node, pak->from->partial);
3072 goto done;
3073 }
3074
3075 if (ast_xmpp_client_send(client, iq)) {
3076 ast_log(LOG_WARNING, "Could not send response to service discovery items request from '%s' on component '%s'\n",
3077 pak->from->partial, client->name);
3078 }
3079
3080done:
3081 iks_delete(feature);
3082 iks_delete(item);
3083 iks_delete(query);
3084 iks_delete(iq);
3085
3086 return IKS_FILTER_EAT;
3087}

References ao2_cleanup, ao2_global_obj_ref, ast_log, ast_xmpp_client_send(), done, globals, item, LOG_ERROR, LOG_WARNING, ast_xmpp_client::name, NULL, RAII_VAR, and xmpp_config_find().

Referenced by xmpp_component_authenticating().

◆ xmpp_config_alloc()

static void * xmpp_config_alloc ( void  )
static

Allocator for XMPP configuration.

Definition at line 724 of file res_xmpp.c.

725{
726 struct xmpp_config *cfg;
727
728 if (!(cfg = ao2_alloc(sizeof(*cfg), xmpp_config_destructor))) {
729 return NULL;
730 }
731
732 if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), NULL))) {
733 goto error;
734 }
735
738 if (!cfg->clients) {
739 goto error;
740 }
741
742 return cfg;
743error:
744 ao2_ref(cfg, -1);
745 return NULL;
746}
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
static void xmpp_config_destructor(void *obj)
Destructor for XMPP configuration.
Definition: res_xmpp.c:708
static int xmpp_config_cmp(void *obj, void *arg, int flags)
Comparator function for configuration.
Definition: res_xmpp.c:716
struct ao2_container * clients
Definition: res_xmpp.c:475
struct ast_xmpp_global_config * global
Definition: res_xmpp.c:474

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, ao2_ref, xmpp_config::clients, error(), xmpp_config::global, NULL, xmpp_config_cmp(), and xmpp_config_destructor().

◆ xmpp_config_cmp()

static int xmpp_config_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Comparator function for configuration.

Definition at line 716 of file res_xmpp.c.

717{
718 struct ast_xmpp_client_config *one = obj, *two = arg;
719 const char *match = (flags & OBJ_KEY) ? arg : two->name;
720 return strcasecmp(one->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
721}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2362

References CMP_MATCH, CMP_STOP, ast_xmpp_client_config::flags, match(), ast_xmpp_client_config::name, and OBJ_KEY.

Referenced by xmpp_config_alloc().

◆ xmpp_config_destructor()

static void xmpp_config_destructor ( void *  obj)
static

Destructor for XMPP configuration.

Definition at line 708 of file res_xmpp.c.

709{
710 struct xmpp_config *cfg = obj;
711 ao2_cleanup(cfg->global);
712 ao2_cleanup(cfg->clients);
713}

References ao2_cleanup, xmpp_config::clients, and xmpp_config::global.

Referenced by xmpp_config_alloc().

◆ xmpp_config_find()

static void * xmpp_config_find ( struct ao2_container tmp_container,
const char *  category 
)
static

◆ xmpp_config_post_apply()

static void xmpp_config_post_apply ( void  )
static

Definition at line 793 of file res_xmpp.c.

794{
796
798}
static int xmpp_client_config_post_apply(void *obj, void *arg, int flags)
Definition: res_xmpp.c:3863

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, globals, NULL, OBJ_MULTIPLE, OBJ_NODATA, RAII_VAR, and xmpp_client_config_post_apply().

◆ xmpp_config_prelink()

static int xmpp_config_prelink ( void *  newitem)
static

Definition at line 748 of file res_xmpp.c.

749{
750 struct ast_xmpp_client_config *clientcfg = newitem;
752 RAII_VAR(struct ast_xmpp_client_config *, oldclientcfg, NULL, ao2_cleanup);
753
754 if (ast_strlen_zero(clientcfg->user)) {
755 ast_log(LOG_ERROR, "No user specified on client '%s'\n", clientcfg->name);
756 return -1;
757 } else if (ast_strlen_zero(clientcfg->password) && ast_strlen_zero(clientcfg->refresh_token)) {
758 ast_log(LOG_ERROR, "No password or refresh_token specified on client '%s'\n", clientcfg->name);
759 return -1;
760 } else if (ast_strlen_zero(clientcfg->server)) {
761 ast_log(LOG_ERROR, "No server specified on client '%s'\n", clientcfg->name);
762 return -1;
763 } else if (!ast_strlen_zero(clientcfg->refresh_token) &&
764 (ast_strlen_zero(clientcfg->oauth_clientid) || ast_strlen_zero(clientcfg->oauth_secret))) {
765 ast_log(LOG_ERROR, "No oauth_clientid or oauth_secret specified, so client '%s' can't be used\n", clientcfg->name);
766 return -1;
767 }
768
769 /* If this is a new connection force a reconnect */
770 if (!cfg || !cfg->clients || !(oldclientcfg = xmpp_config_find(cfg->clients, clientcfg->name))) {
771 clientcfg->client->reconnect = 1;
772 return 0;
773 }
774
775 /* If any configuration options are changing that would require reconnecting set the bit so we will do so if possible */
776 if (strcmp(clientcfg->user, oldclientcfg->user) ||
777 strcmp(clientcfg->password, oldclientcfg->password) ||
778 strcmp(clientcfg->refresh_token, oldclientcfg->refresh_token) ||
779 strcmp(clientcfg->oauth_clientid, oldclientcfg->oauth_clientid) ||
780 strcmp(clientcfg->oauth_secret, oldclientcfg->oauth_secret) ||
781 strcmp(clientcfg->server, oldclientcfg->server) ||
782 (clientcfg->port != oldclientcfg->port) ||
783 (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) != ast_test_flag(&oldclientcfg->flags, XMPP_COMPONENT)) ||
784 (clientcfg->priority != oldclientcfg->priority)) {
785 clientcfg->client->reconnect = 1;
786 } else {
787 clientcfg->client->reconnect = 0;
788 }
789
790 return 0;
791}
const ast_string_field server
Definition: res_xmpp.c:462

References ao2_cleanup, ao2_global_obj_ref, ast_log, ast_strlen_zero(), ast_test_flag, ast_xmpp_client_config::client, ast_xmpp_client_config::flags, globals, LOG_ERROR, ast_xmpp_client_config::name, NULL, ast_xmpp_client_config::oauth_clientid, ast_xmpp_client_config::oauth_secret, ast_xmpp_client_config::password, ast_xmpp_client_config::port, ast_xmpp_client_config::priority, RAII_VAR, ast_xmpp_client::reconnect, ast_xmpp_client_config::refresh_token, ast_xmpp_client_config::server, ast_xmpp_client_config::user, XMPP_COMPONENT, and xmpp_config_find().

◆ xmpp_connect_hook()

static int xmpp_connect_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when client finishes authenticating with the server.

Definition at line 2433 of file res_xmpp.c.

2434{
2436 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2437 struct ast_xmpp_client *client = data;
2438 iks *roster;
2439
2440 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
2441 return -1;
2442 }
2443
2444 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
2445
2446 if (ast_test_flag(&clientcfg->flags, XMPP_DISTRIBUTE_EVENTS)) {
2448 }
2449
2450 if (!(roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER))) {
2451 ast_log(LOG_ERROR, "Unable to allocate memory for roster request for client '%s'\n", client->name);
2452 return -1;
2453 }
2454
2455 iks_filter_add_rule(client->filter, xmpp_client_service_discovery_get_hook, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
2456 iks_filter_add_rule(client->filter, xmpp_client_service_discovery_result_hook, client, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
2457
2458 iks_insert_attrib(roster, "id", "roster");
2459 ast_xmpp_client_send(client, roster);
2460
2461 iks_filter_remove_hook(client->filter, xmpp_connect_hook);
2462 iks_filter_add_rule(client->filter, xmpp_roster_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, "roster", IKS_RULE_DONE);
2463
2464 xmpp_client_set_presence(client, NULL, client->jid->full, clientcfg->status, clientcfg->statusmsg);
2466
2467 return IKS_FILTER_EAT;
2468}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
static int xmpp_client_service_discovery_get_hook(void *data, ikspak *pak)
Hook function called when client receives a service discovery get message.
Definition: res_xmpp.c:2343
static int xmpp_roster_hook(void *data, ikspak *pak)
Hook function called when roster is received from server.
Definition: res_xmpp.c:2247
static void xmpp_init_event_distribution(struct ast_xmpp_client *client)
Initialize collections for event distribution.
Definition: res_xmpp.c:1583
@ XMPP_STATE_ROSTER
Definition: xmpp.h:79

References ao2_cleanup, ao2_global_obj_ref, ast_log, ast_test_flag, ast_xmpp_client_send(), ast_xmpp_client::filter, globals, if(), ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::name, NULL, RAII_VAR, ast_xmpp_client::stack, xmpp_client_change_state(), xmpp_client_service_discovery_get_hook(), xmpp_client_service_discovery_result_hook(), xmpp_client_set_presence(), xmpp_config_find(), xmpp_connect_hook(), XMPP_DISTRIBUTE_EVENTS, xmpp_init_event_distribution(), xmpp_roster_hook(), and XMPP_STATE_ROSTER.

Referenced by xmpp_client_authenticate_digest(), xmpp_client_authenticating(), and xmpp_connect_hook().

◆ xmpp_do_set_debug()

static char * xmpp_do_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4300 of file res_xmpp.c.

4301{
4302 switch (cmd) {
4303 case CLI_INIT:
4304 e->command = "xmpp set debug {on|off}";
4305 e->usage =
4306 "Usage: xmpp set debug {on|off}\n"
4307 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n";
4308 return NULL;
4309 case CLI_GENERATE:
4310 return NULL;
4311 }
4312
4313 if (a->argc != e->args) {
4314 return CLI_SHOWUSAGE;
4315 }
4316
4317 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
4318 debug = 1;
4319 ast_cli(a->fd, "XMPP Debugging Enabled.\n");
4320 return CLI_SUCCESS;
4321 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
4322 debug = 0;
4323 ast_cli(a->fd, "XMPP Debugging Disabled.\n");
4324 return CLI_SUCCESS;
4325 }
4326 return CLI_SHOWUSAGE; /* defaults to invalid */
4327}
int args
This gets set in ast_cli_register()
Definition: cli.h:185

References a, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, debug, NULL, and ast_cli_entry::usage.

◆ xmpp_init_event_distribution()

static void xmpp_init_event_distribution ( struct ast_xmpp_client client)
static

Initialize collections for event distribution.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server

Definition at line 1583 of file res_xmpp.c.

1584{
1586 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1587 RAII_VAR(struct ao2_container *, cached, NULL, ao2_cleanup);
1588
1589 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
1590 return;
1591 }
1592
1593 xmpp_pubsub_unsubscribe(client, "device_state");
1594 xmpp_pubsub_unsubscribe(client, "message_waiting");
1595
1597 return;
1598 }
1601
1603 client->mwi_sub = stasis_unsubscribe(client->mwi_sub);
1604 return;
1605 }
1608
1610 ao2_callback(cached, OBJ_NODATA, cached_devstate_cb, client);
1611
1612 xmpp_pubsub_subscribe(client, "device_state");
1613 xmpp_pubsub_subscribe(client, "message_waiting");
1614 iks_filter_add_rule(client->filter, xmpp_pubsub_handle_event, client, IKS_RULE_TYPE,
1615 IKS_PAK_MESSAGE, IKS_RULE_FROM, clientcfg->pubsubnode, IKS_RULE_DONE);
1616 iks_filter_add_rule(client->filter, xmpp_pubsub_handle_error, client, IKS_RULE_TYPE,
1617 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE);
1618
1619}
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
struct stasis_topic * ast_mwi_topic_all(void)
Get the Stasis Message Bus API topic for MWI messages.
Definition: mwi.c:89
static void xmpp_pubsub_subscribe(struct ast_xmpp_client *client, const char *node)
Subscribe to a PubSub node.
Definition: res_xmpp.c:1410
static void xmpp_pubsub_mwi_cb(void *data, struct stasis_subscription *sub, struct stasis_message *msg)
Callback function for MWI events.
Definition: res_xmpp.c:1335
static int cached_devstate_cb(void *obj, void *arg, int flags)
Definition: res_xmpp.c:1571
static int xmpp_pubsub_handle_error(void *data, ikspak *pak)
Definition: res_xmpp.c:1503
static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
Callback for handling PubSub events.
Definition: res_xmpp.c:1457
struct ao2_container * stasis_cache_dump(struct stasis_cache *cache, struct stasis_message_type *type)
Dump cached items to a subscription for the ast_eid_default entity.
Definition: stasis_cache.c:736
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1023
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1077
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:680
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:971
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, ast_device_state_cache(), ast_device_state_message_type(), ast_device_state_topic_all(), ast_mwi_state_type(), ast_mwi_topic_all(), cached_devstate_cb(), ast_xmpp_client::device_state_sub, ast_xmpp_client::filter, globals, ast_xmpp_client::mwi_sub, ast_xmpp_client::name, NULL, OBJ_NODATA, RAII_VAR, stasis_cache_dump(), stasis_subscribe, stasis_subscribe_pool, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), stasis_unsubscribe(), xmpp_config_find(), xmpp_pubsub_devstate_cb(), xmpp_pubsub_handle_error(), xmpp_pubsub_handle_event(), xmpp_pubsub_mwi_cb(), xmpp_pubsub_subscribe(), and xmpp_pubsub_unsubscribe().

Referenced by xmpp_connect_hook().

◆ xmpp_io_recv()

static int xmpp_io_recv ( struct ast_xmpp_client client,
char *  buffer,
size_t  buf_len,
int  timeout 
)
static

Internal function which polls on an XMPP client and receives data.

Definition at line 3614 of file res_xmpp.c.

3615{
3616 struct pollfd pfd = { .events = POLLIN };
3617 int len, res;
3618
3619#ifdef HAVE_OPENSSL
3620 if (xmpp_is_secure(client)) {
3621 pfd.fd = SSL_get_fd(client->ssl_session);
3622 if (pfd.fd < 0) {
3623 return -1;
3624 }
3625 } else
3626#endif /* HAVE_OPENSSL */
3627 pfd.fd = iks_fd(client->parser);
3628
3629 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
3630 if (res > 0) {
3631#ifdef HAVE_OPENSSL
3632 if (xmpp_is_secure(client)) {
3633 len = SSL_read(client->ssl_session, buffer, buf_len);
3634 } else
3635#endif /* HAVE_OPENSSL */
3636 len = recv(pfd.fd, buffer, buf_len, 0);
3637
3638 if (len > 0) {
3639 return len;
3640 } else if (len <= 0) {
3641 return -1;
3642 }
3643 }
3644 return res;
3645}
#define ast_poll(a, b, c)
Definition: poll-compat.h:88

References ast_poll, len(), ast_xmpp_client::parser, and xmpp_is_secure().

Referenced by xmpp_client_receive().

◆ xmpp_is_secure()

static int xmpp_is_secure ( struct ast_xmpp_client client)
static

Helper function which returns whether an XMPP client connection is secure or not.

Definition at line 872 of file res_xmpp.c.

873{
874#ifdef HAVE_OPENSSL
875 return client->stream_flags & SECURE;
876#else
877 return 0;
878#endif
879}

Referenced by xmpp_client_authenticate_sasl(), xmpp_client_request_tls(), xmpp_client_send_raw_message(), and xmpp_io_recv().

◆ xmpp_join_exec()

static int xmpp_join_exec ( struct ast_channel chan,
const char *  data 
)
static

Application to join a chat room.

Parameters
chanast_channel
dataData is sender|jid|nickname.
Return values
0success
-1error

Definition at line 1718 of file res_xmpp.c.

1719{
1721 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1722 char *s, nick[XMPP_MAX_RESJIDLEN];
1724 AST_APP_ARG(sender);
1725 AST_APP_ARG(jid);
1726 AST_APP_ARG(nick);
1727 );
1728
1729 if (ast_strlen_zero(data)) {
1730 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
1731 return -1;
1732 }
1733 s = ast_strdupa(data);
1734
1736 if (args.argc < 2 || args.argc > 3) {
1737 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
1738 return -1;
1739 }
1740
1741 if (strchr(args.jid, '/')) {
1742 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n");
1743 return -1;
1744 }
1745
1746 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1747 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
1748 return -1;
1749 }
1750
1751 if (ast_strlen_zero(args.nick)) {
1752 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1753 snprintf(nick, sizeof(nick), "asterisk");
1754 } else {
1755 snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
1756 }
1757 } else {
1758 snprintf(nick, sizeof(nick), "%s", args.nick);
1759 }
1760
1761 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) {
1762 ast_xmpp_chatroom_join(clientcfg->client, args.jid, nick);
1763 } else {
1764 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid);
1765 }
1766
1767 return 0;
1768}
int ast_xmpp_chatroom_join(struct ast_xmpp_client *client, const char *room, const char *nickname)
Join an XMPP multi-user chatroom.
Definition: res_xmpp.c:1010
#define XMPP_MAX_RESJIDLEN
Maximum size of a resource JID.
Definition: xmpp.h:65

References ao2_cleanup, ao2_global_obj_ref, app_ajijoin, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_xmpp_chatroom_join(), globals, LOG_ERROR, NULL, RAII_VAR, XMPP_COMPONENT, xmpp_config_find(), and XMPP_MAX_RESJIDLEN.

Referenced by load_module().

◆ xmpp_leave_exec()

static int xmpp_leave_exec ( struct ast_channel chan,
const char *  data 
)
static

Application to leave a chat room.

Parameters
chanast_channel
dataData is sender|jid|nickname.
Return values
0success
-1error

Definition at line 1777 of file res_xmpp.c.

1778{
1780 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1781 char *s, nick[XMPP_MAX_RESJIDLEN];
1783 AST_APP_ARG(sender);
1784 AST_APP_ARG(jid);
1785 AST_APP_ARG(nick);
1786 );
1787
1788 if (ast_strlen_zero(data)) {
1789 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
1790 return -1;
1791 }
1792 s = ast_strdupa(data);
1793
1795 if (args.argc < 2 || args.argc > 3) {
1796 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
1797 return -1;
1798 }
1799
1800 if (strchr(args.jid, '/')) {
1801 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n");
1802 return -1;
1803 }
1804
1805 if (ast_strlen_zero(args.jid) || !strchr(args.jid, '@')) {
1806 ast_log(LOG_ERROR, "No jabber ID specified\n");
1807 return -1;
1808 }
1809
1810 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1811 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
1812 return -1;
1813 }
1814
1815 if (ast_strlen_zero(args.nick)) {
1816 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1817 snprintf(nick, sizeof(nick), "asterisk");
1818 } else {
1819 snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
1820 }
1821 } else {
1822 snprintf(nick, sizeof(nick), "%s", args.nick);
1823 }
1824
1825 ast_xmpp_chatroom_leave(clientcfg->client, args.jid, nick);
1826
1827 return 0;
1828}
int ast_xmpp_chatroom_leave(struct ast_xmpp_client *client, const char *room, const char *nickname)
Leave an XMPP multi-user chatroom.
Definition: res_xmpp.c:1020

References ao2_cleanup, ao2_global_obj_ref, app_ajileave, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_xmpp_chatroom_leave(), globals, LOG_ERROR, NULL, RAII_VAR, XMPP_COMPONENT, xmpp_config_find(), and XMPP_MAX_RESJIDLEN.

Referenced by load_module().

◆ xmpp_log_hook()

static void xmpp_log_hook ( void *  data,
const char *  xmpp,
size_t  size,
int  incoming 
)
static

Logging hook function.

Definition at line 2471 of file res_xmpp.c.

2472{
2474 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2475 struct ast_xmpp_client *client = data;
2476
2477 if (!debug && (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) || !ast_test_flag(&clientcfg->flags, XMPP_DEBUG))) {
2478 return;
2479 }
2480
2481 if (!incoming) {
2482 ast_verbose("\n<--- XMPP sent to '%s' --->\n%s\n<------------->\n", client->name, xmpp);
2483 } else {
2484 ast_verbose("\n<--- XMPP received from '%s' --->\n%s\n<------------->\n", client->name, xmpp);
2485 }
2486}
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206

References ao2_cleanup, ao2_global_obj_ref, ast_test_flag, ast_verbose(), debug, globals, ast_xmpp_client::name, NULL, RAII_VAR, xmpp_config_find(), and XMPP_DEBUG.

Referenced by xmpp_client_config_post_apply(), xmpp_client_receive(), and xmpp_client_send_raw_message().

◆ xmpp_message_destroy()

static void xmpp_message_destroy ( struct ast_xmpp_message message)
static

Destroy function for XMPP messages.

Definition at line 538 of file res_xmpp.c.

539{
540 if (message->from) {
541 ast_free(message->from);
542 }
543 if (message->message) {
544 ast_free(message->message);
545 }
546
548}

References ast_free.

Referenced by acf_jabberreceive_read(), delete_old_messages(), and xmpp_client_destructor().

◆ xmpp_pak_message()

static int xmpp_pak_message ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
iks *  node,
ikspak *  pak 
)
static

Internal function called when a message is received.

Definition at line 3117 of file res_xmpp.c.

3118{
3119 struct ast_xmpp_message *message;
3120 char *body;
3121 int deleted = 0;
3122
3123 ast_debug(3, "XMPP client '%s' received a message\n", client->name);
3124
3125 if (!(body = iks_find_cdata(pak->x, "body"))) {
3126 /* Message contains no body, ignore it. */
3127 return 0;
3128 }
3129
3130 if (!(message = ast_calloc(1, sizeof(*message)))) {
3131 return -1;
3132 }
3133
3134 message->arrived = ast_tvnow();
3135
3136 message->message = ast_strdup(body);
3137
3138 ast_copy_string(message->id, S_OR(pak->id, ""), sizeof(message->id));
3139 message->from = !ast_strlen_zero(pak->from->full) ? ast_strdup(pak->from->full) : NULL;
3140
3142 struct ast_msg *msg;
3143 struct ast_xmpp_buddy *buddy;
3144
3145 if ((msg = ast_msg_alloc())) {
3146 int res;
3147
3148 ast_xmpp_client_lock(client);
3149
3150 buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY | OBJ_NOLOCK);
3151
3152 res = ast_msg_set_to(msg, "xmpp:%s", cfg->user);
3153 res |= ast_msg_set_from(msg, "xmpp:%s", message->from);
3154 res |= ast_msg_set_body(msg, "%s", message->message);
3155 res |= ast_msg_set_context(msg, "%s", cfg->context);
3156 res |= ast_msg_set_tech(msg, "%s", "XMPP");
3157 res |= ast_msg_set_endpoint(msg, "%s", client->name);
3158
3159 if (buddy) {
3160 res |= ast_msg_set_var(msg, "XMPP_BUDDY", buddy->id);
3161 }
3162
3163 ao2_cleanup(buddy);
3164
3165 ast_xmpp_client_unlock(client);
3166
3167 if (res) {
3168 ast_msg_destroy(msg);
3169 } else {
3170 ast_msg_queue(msg);
3171 }
3172 }
3173 }
3174
3175 /* remove old messages received from this JID
3176 * and insert received message */
3177 deleted = delete_old_messages(client, pak->from->partial);
3178 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial);
3179 AST_LIST_LOCK(&client->messages);
3180 AST_LIST_INSERT_HEAD(&client->messages, message, list);
3181 AST_LIST_UNLOCK(&client->messages);
3182
3183 /* wake up threads waiting for messages */
3187
3188 return 0;
3189}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define ast_cond_broadcast(cond)
Definition: lock.h:204
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
Definition: main/message.c:479
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: main/message.c:462
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
Definition: main/message.c:534
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: main/message.c:523
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: main/message.c:432
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message going to the dialplan.
Definition: main/message.c:629
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: main/message.c:501
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
Definition: main/message.c:490
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
Definition: main/message.c:468
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: main/message.c:972
static int delete_old_messages(struct ast_xmpp_client *client, char *from)
Definition: res_xmpp.c:2092
A message.
Definition: main/message.c:247
const ast_string_field context
Definition: res_xmpp.c:462

References ao2_cleanup, ao2_find, ast_calloc, ast_cond_broadcast, ast_copy_string(), ast_debug, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_msg_alloc(), ast_msg_destroy(), ast_msg_queue(), ast_msg_set_body(), ast_msg_set_context(), ast_msg_set_endpoint(), ast_msg_set_from(), ast_msg_set_tech(), ast_msg_set_to(), ast_msg_set_var(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_strlen_zero(), ast_test_flag, ast_tvnow(), ast_xmpp_client_lock(), ast_xmpp_client_unlock(), ast_xmpp_client::buddies, ast_xmpp_client_config::context, delete_old_messages(), ast_xmpp_client_config::flags, ast_xmpp_buddy::id, ast_xmpp_message::message, message_received_condition, messagelock, ast_xmpp_client::messages, ast_xmpp_client::name, NULL, OBJ_KEY, OBJ_NOLOCK, S_OR, ast_xmpp_client_config::user, and XMPP_SEND_TO_DIALPLAN.

◆ xmpp_pak_presence()

static int xmpp_pak_presence ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
iks *  node,
ikspak *  pak 
)
static

Internal function called when a presence message is received.

Definition at line 3263 of file res_xmpp.c.

3264{
3265 struct ast_xmpp_buddy *buddy;
3267 char *type = iks_find_attrib(pak->x, "type");
3268 int status = pak->show ? pak->show : STATUS_DISAPPEAR;
3270
3271 /* If this is a component presence probe request answer immediately with our presence status */
3272 if (ast_test_flag(&cfg->flags, XMPP_COMPONENT) && !ast_strlen_zero(type) && !strcasecmp(type, "probe")) {
3273 xmpp_client_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), cfg->status, cfg->statusmsg);
3274 }
3275
3276 /* If no resource is available this is a general buddy presence update, which we will ignore */
3277 if (!pak->from->resource) {
3278 return 0;
3279 }
3280
3281 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY))) {
3282 /* Only output the message if it is not about us */
3283 if (strcmp(client->jid->partial, pak->from->partial)) {
3284 ast_log(LOG_WARNING, "Received presence information about '%s' despite not having them in roster on client '%s'\n",
3285 pak->from->partial, client->name);
3286 }
3287 return 0;
3288 }
3289
3290 ao2_lock(buddy->resources);
3291
3292 if (!(resource = ao2_callback(buddy->resources, OBJ_NOLOCK, xmpp_resource_cmp, pak->from->resource))) {
3293 /* Only create the new resource if it is not going away - in reality this should not happen */
3294 if (status != STATUS_DISAPPEAR) {
3296 ast_log(LOG_ERROR, "Could not allocate resource object for resource '%s' of buddy '%s' on client '%s'\n",
3297 pak->from->resource, buddy->id, client->name);
3298 ao2_unlock(buddy->resources);
3299 ao2_ref(buddy, -1);
3300 return 0;
3301 }
3302
3303 ast_copy_string(resource->resource, pak->from->resource, sizeof(resource->resource));
3304 }
3305 } else {
3306 /* We unlink the resource in case the priority changes or in case they are going away */
3308 }
3309
3310 /* Only update the resource and add it back in if it is not going away */
3311 if (resource && (status != STATUS_DISAPPEAR)) {
3312 char *node, *ver;
3313
3314 /* Try to get the XMPP spec node, and fall back to Google if not found */
3315 if (!(node = iks_find_attrib(iks_find(pak->x, "c"), "node"))) {
3316 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node");
3317 }
3318
3319 if (!(ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"))) {
3320 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver");
3321 }
3322
3323 if (resource->description) {
3324 ast_free(resource->description);
3325 }
3326
3327 if ((node && strcmp(resource->caps.node, node)) || (ver && strcmp(resource->caps.version, ver))) {
3328 /* For interoperability reasons, proceed even if the resource fails to provide node or version */
3329 if (node) {
3330 ast_copy_string(resource->caps.node, node, sizeof(resource->caps.node));
3331 }
3332 if (ver) {
3333 ast_copy_string(resource->caps.version, ver, sizeof(resource->caps.version));
3334 }
3335
3336 /* Google Talk places the capabilities information directly in presence, so see if it is there */
3337 if (iks_find_with_attrib(pak->x, "c", "node", "http://www.google.com/xmpp/client/caps") ||
3338 iks_find_with_attrib(pak->x, "caps:c", "node", "http://www.google.com/xmpp/client/caps") ||
3339 iks_find_with_attrib(pak->x, "c", "node", "http://www.android.com/gtalk/client/caps") ||
3340 iks_find_with_attrib(pak->x, "caps:c", "node", "http://www.android.com/gtalk/client/caps") ||
3341 iks_find_with_attrib(pak->x, "c", "node", "http://mail.google.com/xmpp/client/caps") ||
3342 iks_find_with_attrib(pak->x, "caps:c", "node", "http://mail.google.com/xmpp/client/caps")) {
3343 resource->caps.google = 1;
3344 }
3345
3346 /* To discover if the buddy supports Jingle we need to query, so do so */
3347 if (xmpp_client_send_disco_info_request(client, pak->from->full, client->jid->full)) {
3348 ast_log(LOG_WARNING, "Could not send discovery information request to resource '%s' of buddy '%s' on client '%s', capabilities may be incomplete\n", resource->resource, buddy->id, client->name);
3349 }
3350 }
3351
3352 resource->status = status;
3353 resource->description = ast_strdup(iks_find_cdata(pak->x, "status"));
3354 resource->priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
3355
3357
3358 manager_event(EVENT_FLAG_USER, "JabberStatus",
3359 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d"
3360 "\r\nDescription: %s\r\n",
3361 client->name, pak->from->partial, resource->resource, resource->status,
3362 resource->priority, S_OR(resource->description, ""));
3363
3364 ao2_ref(resource, -1);
3365 } else {
3366 /* This will get hit by presence coming in for an unknown resource, and also when a resource goes away */
3367 if (resource) {
3368 ao2_ref(resource, -1);
3369 }
3370
3371 manager_event(EVENT_FLAG_USER, "JabberStatus",
3372 "Account: %s\r\nJID: %s\r\nStatus: %u\r\n",
3373 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE);
3374 }
3375
3376 /* Determine if at least one resource is available for device state purposes */
3379 ao2_ref(resource, -1);
3380 }
3381
3382 ao2_unlock(buddy->resources);
3383
3384 ao2_ref(buddy, -1);
3385
3386 ast_devstate_changed(state, AST_DEVSTATE_CACHABLE, "XMPP/%s/%s", client->name, pak->from->partial);
3387
3388 return 0;
3389}
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
#define EVENT_FLAG_USER
Definition: manager.h:81
static int xmpp_resource_is_available(void *obj, void *arg, int flags)
Callback function which returns when the resource is available.
Definition: res_xmpp.c:3221
#define STATUS_DISAPPEAR
Status for a disappearing buddy.
Definition: res_xmpp.c:438
static void xmpp_resource_destructor(void *obj)
Destructor callback function for XMPP resource.
Definition: res_xmpp.c:835
static int xmpp_client_send_disco_info_request(struct ast_xmpp_client *client, const char *to, const char *from)
Helper function which sends a discovery information request to a user.
Definition: res_xmpp.c:3192

References ao2_alloc, ao2_callback, ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ast_copy_string(), AST_DEVICE_NOT_INUSE, AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_free, ast_log, ast_strdup, ast_strlen_zero(), ast_test_flag, ast_xmpp_client::buddies, EVENT_FLAG_USER, ast_xmpp_client_config::flags, ast_xmpp_buddy::id, ast_xmpp_client::jid, LOG_ERROR, LOG_WARNING, manager_event, ast_xmpp_client::name, NULL, OBJ_KEY, OBJ_NOLOCK, ast_xmpp_resource::resource, ast_xmpp_buddy::resources, S_OR, status, ast_xmpp_client_config::status, STATUS_DISAPPEAR, ast_xmpp_client_config::statusmsg, type, xmpp_client_send_disco_info_request(), xmpp_client_set_presence(), XMPP_COMPONENT, xmpp_resource_cmp(), xmpp_resource_destructor(), and xmpp_resource_is_available().

◆ xmpp_pak_s10n()

static int xmpp_pak_s10n ( struct ast_xmpp_client client,
struct ast_xmpp_client_config cfg,
iks *  node,
ikspak *  pak 
)
static

Internal function called when a subscription message is received.

Definition at line 3392 of file res_xmpp.c.

3393{
3394 struct ast_xmpp_buddy *buddy;
3395
3396 switch (pak->subtype) {
3397 case IKS_TYPE_SUBSCRIBE:
3399 iks *presence, *status = NULL;
3400
3401 if ((presence = iks_new("presence")) && (status = iks_new("status"))) {
3402 iks_insert_attrib(presence, "type", "subscribed");
3403 iks_insert_attrib(presence, "to", pak->from->full);
3404 iks_insert_attrib(presence, "from", client->jid->full);
3405
3406 if (pak->id) {
3407 iks_insert_attrib(presence, "id", pak->id);
3408 }
3409
3410 iks_insert_cdata(status, "Asterisk has approved your subscription", 0);
3411 iks_insert_node(presence, status);
3412
3413 if (ast_xmpp_client_send(client, presence)) {
3414 ast_log(LOG_ERROR, "Could not send subscription acceptance to '%s' from client '%s'\n",
3415 pak->from->partial, client->name);
3416 }
3417 } else {
3418 ast_log(LOG_ERROR, "Could not allocate presence stanzas for accepting subscription from '%s' to client '%s'\n",
3419 pak->from->partial, client->name);
3420 }
3421
3422 iks_delete(status);
3423 iks_delete(presence);
3424 }
3425
3426 if (ast_test_flag(&cfg->flags, XMPP_COMPONENT)) {
3427 xmpp_client_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), cfg->status, cfg->statusmsg);
3428 }
3429 /* This purposely flows through so we have the subscriber amongst our buddies */
3430 case IKS_TYPE_SUBSCRIBED:
3431 ao2_lock(client->buddies);
3432
3433 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY | OBJ_NOLOCK))) {
3434 buddy = xmpp_client_create_buddy(client->buddies, pak->from->partial);
3435 }
3436
3437 if (!buddy) {
3438 ast_log(LOG_WARNING, "Could not find or create buddy '%s' on client '%s'\n",
3439 pak->from->partial, client->name);
3440 } else {
3441 ao2_ref(buddy, -1);
3442 }
3443
3444 ao2_unlock(client->buddies);
3445
3446 break;
3447 default:
3448 break;
3449 }
3450
3451 return 0;
3452}

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_log, ast_test_flag, ast_xmpp_client_send(), ast_xmpp_client::buddies, ast_xmpp_client_config::flags, ast_xmpp_client::jid, LOG_ERROR, LOG_WARNING, ast_xmpp_client::name, NULL, OBJ_KEY, OBJ_NOLOCK, status, ast_xmpp_client_config::status, ast_xmpp_client_config::statusmsg, XMPP_AUTOREGISTER, xmpp_client_create_buddy(), xmpp_client_set_presence(), and XMPP_COMPONENT.

◆ xmpp_ping_request()

static int xmpp_ping_request ( struct ast_xmpp_client client,
const char *  to,
const char *  from 
)
static

Helper function which sends a ping request to a server.

Definition at line 3229 of file res_xmpp.c.

3230{
3231 iks *iq, *ping;
3232 int res;
3233
3234 ast_debug(2, "JABBER: Sending Keep-Alive Ping for client '%s'\n", client->name);
3235
3236 if (!(iq = iks_new("iq")) || !(ping = iks_new("ping"))) {
3237 iks_delete(iq);
3238 return -1;
3239 }
3240
3241 iks_insert_attrib(iq, "type", "get");
3242 iks_insert_attrib(iq, "to", to);
3243 iks_insert_attrib(iq, "from", from);
3244
3245 ast_xmpp_client_lock(client);
3246 iks_insert_attrib(iq, "id", client->mid);
3247 ast_xmpp_increment_mid(client->mid);
3248 ast_xmpp_client_unlock(client);
3249
3250 iks_insert_attrib(ping, "xmlns", "urn:xmpp:ping");
3251 iks_insert_node(iq, ping);
3252
3253 res = ast_xmpp_client_send(client, iq);
3254
3255 iks_delete(ping);
3256 iks_delete(iq);
3257
3258
3259 return res;
3260}

References ast_debug, ast_xmpp_client_lock(), ast_xmpp_client_send(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), ast_xmpp_client::mid, and ast_xmpp_client::name.

Referenced by xmpp_client_receive(), and xmpp_client_thread().

◆ xmpp_pubsub_build_node_config()

static iks * xmpp_pubsub_build_node_config ( iks *  pubsub,
const char *  node_type,
const char *  collection_name 
)
static

Definition at line 1114 of file res_xmpp.c.

1115{
1116 iks *configure, *x, *field_owner, *field_node_type, *field_node_config,
1117 *field_deliver_payload, *field_persist_items, *field_access_model,
1118 *field_pubsub_collection;
1119 configure = iks_insert(pubsub, "configure");
1120 x = iks_insert(configure, "x");
1121 iks_insert_attrib(x, "xmlns", "jabber:x:data");
1122 iks_insert_attrib(x, "type", "submit");
1123 field_owner = iks_insert(x, "field");
1124 iks_insert_attrib(field_owner, "var", "FORM_TYPE");
1125 iks_insert_attrib(field_owner, "type", "hidden");
1126 iks_insert_cdata(iks_insert(field_owner, "value"),
1127 "http://jabber.org/protocol/pubsub#owner", 39);
1128 if (node_type) {
1129 field_node_type = iks_insert(x, "field");
1130 iks_insert_attrib(field_node_type, "var", "pubsub#node_type");
1131 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type));
1132 }
1133 field_node_config = iks_insert(x, "field");
1134 iks_insert_attrib(field_node_config, "var", "FORM_TYPE");
1135 iks_insert_attrib(field_node_config, "type", "hidden");
1136 iks_insert_cdata(iks_insert(field_node_config, "value"),
1137 "http://jabber.org/protocol/pubsub#node_config", 45);
1138 field_deliver_payload = iks_insert(x, "field");
1139 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads");
1140 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1);
1141 field_persist_items = iks_insert(x, "field");
1142 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items");
1143 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1);
1144 field_access_model = iks_insert(x, "field");
1145 iks_insert_attrib(field_access_model, "var", "pubsub#access_model");
1146 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9);
1147 if (node_type && !strcasecmp(node_type, "leaf")) {
1148 field_pubsub_collection = iks_insert(x, "field");
1149 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection");
1150 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name,
1151 strlen(collection_name));
1152 }
1153 return configure;
1154}
node_type
Definition: ast_expr2.c:333

Referenced by xmpp_pubsub_create_node().

◆ xmpp_pubsub_build_node_request()

static iks * xmpp_pubsub_build_node_request ( struct ast_xmpp_client client,
const char *  collection 
)
static

Build the a node request.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
collectionname of the collection for request
Returns
iks *

Definition at line 3974 of file res_xmpp.c.

3975{
3976 iks *request = xmpp_pubsub_iq_create(client, "get"), *query;
3977
3978 if (!request) {
3979 return NULL;
3980 }
3981
3982 query = iks_insert(request, "query");
3983 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
3984
3985 if (collection) {
3986 iks_insert_attrib(query, "node", collection);
3987 }
3988
3989 return request;
3990}
static int request(void *obj)
Definition: chan_pjsip.c:2601
static iks * xmpp_pubsub_iq_create(struct ast_xmpp_client *client, const char *type)
Create an IQ packet.
Definition: res_xmpp.c:1045

References ast_xmpp_client_config::client, NULL, request(), and xmpp_pubsub_iq_create().

Referenced by xmpp_pubsub_purge_nodes(), and xmpp_pubsub_request_nodes().

◆ xmpp_pubsub_build_publish_skeleton()

static iks * xmpp_pubsub_build_publish_skeleton ( struct ast_xmpp_client client,
const char *  node,
const char *  event_type,
unsigned int  cachable 
)
static

Build the skeleton of a publish.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
nodeName of the node that will be published to
event_type,cachable
Returns
iks *

Definition at line 1077 of file res_xmpp.c.

1079{
1081 iks *request, *pubsub, *publish, *item;
1082
1083 if (!cfg || !cfg->global || !(request = xmpp_pubsub_iq_create(client, "set"))) {
1084 return NULL;
1085 }
1086
1087 pubsub = iks_insert(request, "pubsub");
1088 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1089 publish = iks_insert(pubsub, "publish");
1090 iks_insert_attrib(publish, "node", ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248) ? node : event_type);
1091 item = iks_insert(publish, "item");
1092 iks_insert_attrib(item, "id", node);
1093
1094 if (cachable == AST_DEVSTATE_NOT_CACHABLE) {
1095 iks *options, *x, *field_form_type, *field_persist;
1096
1097 options = iks_insert(pubsub, "publish-options");
1098 x = iks_insert(options, "x");
1099 iks_insert_attrib(x, "xmlns", "jabber:x:data");
1100 iks_insert_attrib(x, "type", "submit");
1101 field_form_type = iks_insert(x, "field");
1102 iks_insert_attrib(field_form_type, "var", "FORM_TYPE");
1103 iks_insert_attrib(field_form_type, "type", "hidden");
1104 iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0);
1105 field_persist = iks_insert(x, "field");
1106 iks_insert_attrib(field_persist, "var", "pubsub#persist_items");
1107 iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1);
1108 }
1109
1110 return item;
1111
1112}
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
unsigned char publish
Definition: res_corosync.c:241
static struct test_options options

References ao2_cleanup, ao2_global_obj_ref, AST_DEVSTATE_NOT_CACHABLE, ast_test_flag, globals, item, NULL, options, publish, RAII_VAR, request(), xmpp_pubsub_iq_create(), and XMPP_XEP0248.

Referenced by xmpp_pubsub_publish_device_state(), and xmpp_pubsub_publish_mwi().

◆ xmpp_pubsub_create_affiliations()

static void xmpp_pubsub_create_affiliations ( struct ast_xmpp_client client,
const char *  node 
)
static

Add Owner affiliations for pubsub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
nodethe name of the node to which to add affiliations

Definition at line 1161 of file res_xmpp.c.

1162{
1163 iks *modify_affiliates = xmpp_pubsub_iq_create(client, "set");
1164 iks *pubsub, *affiliations, *affiliate;
1165 struct ao2_iterator i;
1166 struct ast_xmpp_buddy *buddy;
1167
1168 if (!modify_affiliates) {
1169 ast_log(LOG_ERROR, "Could not create IQ for creating affiliations on client '%s'\n", client->name);
1170 return;
1171 }
1172
1173 pubsub = iks_insert(modify_affiliates, "pubsub");
1174 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner");
1175 affiliations = iks_insert(pubsub, "affiliations");
1176 iks_insert_attrib(affiliations, "node", node);
1177
1178 i = ao2_iterator_init(client->buddies, 0);
1179 while ((buddy = ao2_iterator_next(&i))) {
1180 affiliate = iks_insert(affiliations, "affiliation");
1181 iks_insert_attrib(affiliate, "jid", buddy->id);
1182 iks_insert_attrib(affiliate, "affiliation", "owner");
1183 ao2_ref(buddy, -1);
1184 }
1186
1187 ast_xmpp_client_send(client, modify_affiliates);
1188 iks_delete(modify_affiliates);
1189}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log, ast_xmpp_client_send(), ast_xmpp_client::buddies, ast_xmpp_buddy::id, LOG_ERROR, ast_xmpp_client::name, and xmpp_pubsub_iq_create().

Referenced by xmpp_pubsub_create_node().

◆ xmpp_pubsub_create_collection()

static void xmpp_pubsub_create_collection ( struct ast_xmpp_client client,
const char *  collection_name 
)
static

Create a PubSub collection node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
collection_nameThe name to use for this collection

Definition at line 1244 of file res_xmpp.c.

1245{
1246 xmpp_pubsub_create_node(client, "collection", collection_name, NULL);
1247}
static void xmpp_pubsub_create_node(struct ast_xmpp_client *client, const char *node_type, const char *name, const char *collection_name)
Create a pubsub node.
Definition: res_xmpp.c:1198

References NULL, and xmpp_pubsub_create_node().

Referenced by xmpp_cli_create_collection(), and xmpp_pubsub_handle_error().

◆ xmpp_pubsub_create_leaf()

static void xmpp_pubsub_create_leaf ( struct ast_xmpp_client client,
const char *  collection_name,
const char *  leaf_name 
)
static

Create a PubSub leaf node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
collection_name
leaf_nameThe name to use for this collection

Definition at line 1256 of file res_xmpp.c.

1258{
1259 xmpp_pubsub_create_node(client, "leaf", leaf_name, collection_name);
1260}

References xmpp_pubsub_create_node().

Referenced by xmpp_cli_create_leafnode(), and xmpp_pubsub_handle_error().

◆ xmpp_pubsub_create_node()

static void xmpp_pubsub_create_node ( struct ast_xmpp_client client,
const char *  node_type,
const char *  name,
const char *  collection_name 
)
static

Create a pubsub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
node_typethe type of node to create
namethe name of the node to create
collection_name

Definition at line 1198 of file res_xmpp.c.

1200{
1201 iks *node, *pubsub, *create;
1202
1203 if (!(node = xmpp_pubsub_iq_create(client, "set"))) {
1204 return;
1205 }
1206
1207 pubsub = iks_insert(node, "pubsub");
1208 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1209 create = iks_insert(pubsub, "create");
1210 iks_insert_attrib(create, "node", name);
1211 xmpp_pubsub_build_node_config(pubsub, node_type, collection_name);
1212 ast_xmpp_client_send(client, node);
1214 iks_delete(node);
1215}
static iks * xmpp_pubsub_build_node_config(iks *pubsub, const char *node_type, const char *collection_name)
Definition: res_xmpp.c:1114
static void xmpp_pubsub_create_affiliations(struct ast_xmpp_client *client, const char *node)
Add Owner affiliations for pubsub node.
Definition: res_xmpp.c:1161

References ast_xmpp_client_send(), name, xmpp_pubsub_build_node_config(), xmpp_pubsub_create_affiliations(), and xmpp_pubsub_iq_create().

Referenced by xmpp_pubsub_create_collection(), xmpp_pubsub_create_leaf(), xmpp_pubsub_handle_error(), and xmpp_pubsub_publish_device_state().

◆ xmpp_pubsub_delete_node()

static void xmpp_pubsub_delete_node ( struct ast_xmpp_client client,
const char *  node_name 
)
static

Delete a PubSub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
node_namethe name of the node to delete

Definition at line 1222 of file res_xmpp.c.

1223{
1224 iks *request, *pubsub, *delete;
1225
1226 if (!(request = xmpp_pubsub_iq_create(client, "set"))) {
1227 return;
1228 }
1229
1230 pubsub = iks_insert(request, "pubsub");
1231 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner");
1232 delete = iks_insert(pubsub, "delete");
1233 iks_insert_attrib(delete, "node", node_name);
1235
1236 iks_delete(request);
1237}

References ast_xmpp_client_send(), request(), and xmpp_pubsub_iq_create().

Referenced by xmpp_cli_delete_pubsub_node(), xmpp_cli_purge_pubsub_nodes(), and xmpp_pubsub_delete_node_list().

◆ xmpp_pubsub_delete_node_list()

static int xmpp_pubsub_delete_node_list ( void *  data,
ikspak *  pak 
)
static

Delete pubsub item lists.

Parameters
datapointer to ast_xmpp_client structure
pakresponse from pubsub diso::items query
Return values
IKS_FILTER_EAT

Definition at line 4096 of file res_xmpp.c.

4097{
4098 struct ast_xmpp_client *client = data;
4099 iks *item = NULL;
4100
4101 if (iks_has_children(pak->query)) {
4102 item = iks_first_tag(pak->query);
4103 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial,
4104 iks_find_attrib(item, "node"));
4105 while ((item = iks_next_tag(item))) {
4106 xmpp_pubsub_delete_node(client, iks_find_attrib(item, "node"));
4107 }
4108 }
4109
4110 if (item) {
4111 iks_delete(item);
4112 }
4113
4114 return IKS_FILTER_EAT;
4115}

References ast_log, item, ast_xmpp_client::jid, LOG_WARNING, NULL, and xmpp_pubsub_delete_node().

Referenced by xmpp_pubsub_purge_nodes().

◆ xmpp_pubsub_devstate_cb()

static void xmpp_pubsub_devstate_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Callback function for device state events.

Parameters
datavoid pointer to ast_client structure
sub,msg

Definition at line 1362 of file res_xmpp.c.

1363{
1364 struct ast_xmpp_client *client = data;
1365 struct ast_device_state_message *dev_state;
1366
1368 return;
1369 }
1370
1371 dev_state = stasis_message_data(msg);
1372 if (!dev_state->eid || ast_eid_cmp(&ast_eid_default, dev_state->eid)) {
1373 /* If the event is aggregate or didn't originate from this server, don't send it out. */
1374 return;
1375 }
1376
1377 xmpp_pubsub_publish_device_state(client, dev_state->device, ast_devstate_str(dev_state->state), dev_state->cachable);
1378}
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
struct stasis_forward * sub
Definition: res_corosync.c:240
static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, const char *device, const char *device_state, unsigned int cachable)
Publish device state to a PubSub node.
Definition: res_xmpp.c:1300
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int stasis_subscription_is_subscribed(const struct stasis_subscription *sub)
Returns whether a subscription is currently subscribed.
Definition: stasis.c:1150
The structure that contains device state.
Definition: devicestate.h:238
enum ast_device_state state
Definition: devicestate.h:248
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246
enum ast_devstate_cache cachable
Definition: devicestate.h:250
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: utils.c:3094

References ast_device_state_message_type(), ast_devstate_str(), ast_eid_cmp(), ast_eid_default, ast_device_state_message::cachable, ast_device_state_message::device, ast_device_state_message::eid, stasis_message_data(), stasis_message_type(), stasis_subscription_is_subscribed(), ast_device_state_message::state, sub, and xmpp_pubsub_publish_device_state().

Referenced by cached_devstate_cb(), and xmpp_init_event_distribution().

◆ xmpp_pubsub_handle_error()

static int xmpp_pubsub_handle_error ( void *  data,
ikspak *  pak 
)
static

Definition at line 1503 of file res_xmpp.c.

1504{
1506 char *node_name, *error;
1507 int error_num;
1508 iks *orig_request, *orig_pubsub = iks_find(pak->x, "pubsub");
1509 struct ast_xmpp_client *client = data;
1510
1511 if (!cfg || !cfg->global) {
1512 ast_log(LOG_ERROR, "No global configuration available\n");
1513 return IKS_FILTER_EAT;
1514 }
1515
1516 if (!orig_pubsub) {
1517 ast_debug(1, "Error isn't a PubSub error, why are we here?\n");
1518 return IKS_FILTER_EAT;
1519 }
1520
1521 orig_request = iks_child(orig_pubsub);
1522 error = iks_find_attrib(iks_find(pak->x, "error"), "code");
1523 node_name = iks_find_attrib(orig_request, "node");
1524
1525 if (!sscanf(error, "%30d", &error_num)) {
1526 return IKS_FILTER_EAT;
1527 }
1528
1529 if (error_num > 399 && error_num < 500 && error_num != 404) {
1531 "Error performing operation on PubSub node %s, %s.\n", node_name, error);
1532 return IKS_FILTER_EAT;
1533 } else if (error_num > 499 && error_num < 600) {
1534 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error);
1535 return IKS_FILTER_EAT;
1536 }
1537
1538 if (!strcasecmp(iks_name(orig_request), "publish")) {
1539 iks *request;
1540
1541 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1542 if (iks_find(iks_find(orig_request, "item"), "state")) {
1543 xmpp_pubsub_create_leaf(client, "device_state", node_name);
1544 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) {
1545 xmpp_pubsub_create_leaf(client, "message_waiting", node_name);
1546 }
1547 } else {
1548 xmpp_pubsub_create_node(client, NULL, node_name, NULL);
1549 }
1550
1551 if ((request = xmpp_pubsub_iq_create(client, "set"))) {
1552 iks_insert_node(request, orig_pubsub);
1554 iks_delete(request);
1555 } else {
1556 ast_log(LOG_ERROR, "PubSub publish could not create IQ\n");
1557 }
1558
1559 return IKS_FILTER_EAT;
1560 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) {
1561 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1562 xmpp_pubsub_create_collection(client, node_name);
1563 } else {
1564 xmpp_pubsub_create_node(client, NULL, node_name, NULL);
1565 }
1566 }
1567
1568 return IKS_FILTER_EAT;
1569}

References ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_log, ast_test_flag, ast_xmpp_client_send(), error(), globals, LOG_ERROR, NULL, RAII_VAR, request(), xmpp_pubsub_create_collection(), xmpp_pubsub_create_leaf(), xmpp_pubsub_create_node(), xmpp_pubsub_iq_create(), and XMPP_XEP0248.

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_handle_event()

static int xmpp_pubsub_handle_event ( void *  data,
ikspak *  pak 
)
static

Callback for handling PubSub events.

Parameters
datavoid pointer to ast_xmpp_client structure
pakA pak
Return values
IKS_FILTER_EAT

Definition at line 1457 of file res_xmpp.c.

1458{
1459 char *item_id, *device_state, *mailbox, *cachable_str;
1460 int oldmsgs, newmsgs;
1461 iks *item, *item_content;
1462 struct ast_eid pubsub_eid;
1463 unsigned int cachable = AST_DEVSTATE_CACHABLE;
1464 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item");
1465 if (!item) {
1466 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n");
1467 return IKS_FILTER_EAT;
1468 }
1469 item_id = iks_find_attrib(item, "id");
1470 item_content = iks_child(item);
1471 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid"));
1472 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) {
1473 ast_debug(1, "Returning here, eid of incoming event matches ours!\n");
1474 return IKS_FILTER_EAT;
1475 }
1476 if (!strcasecmp(iks_name(item_content), "state")) {
1477 if ((cachable_str = iks_find_attrib(item_content, "cachable"))) {
1478 sscanf(cachable_str, "%30u", &cachable);
1479 }
1480 device_state = iks_find_cdata(item, "state");
1482 ast_devstate_val(device_state),
1484 &pubsub_eid);
1485 return IKS_FILTER_EAT;
1486 } else if (!strcasecmp(iks_name(item_content), "mailbox")) {
1487 mailbox = strsep(&item_id, "@");
1488 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs);
1489 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs);
1490
1491 ast_publish_mwi_state_full(mailbox, item_id, newmsgs, oldmsgs, NULL, &pubsub_eid);
1492
1493 return IKS_FILTER_EAT;
1494 } else {
1495 ast_debug(1, "Don't know how to handle PubSub event of type %s\n",
1496 iks_name(item_content));
1497 return IKS_FILTER_EAT;
1498 }
1499
1500 return IKS_FILTER_EAT;
1501}
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:260
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
Definition: devicestate.c:709
int ast_publish_mwi_state_full(const char *mailbox, const char *context, int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid)
Publish a MWI state update via stasis with all parameters.
Definition: mwi.c:393
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:813
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: utils.c:3077

References ast_debug, AST_DEVSTATE_CACHABLE, AST_DEVSTATE_NOT_CACHABLE, ast_devstate_val(), ast_eid_cmp(), ast_eid_default, ast_log, ast_publish_device_state_full(), ast_publish_mwi_state_full(), ast_str_to_eid(), item, LOG_ERROR, voicemailpwcheck::mailbox, NULL, and strsep().

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_iq_create()

static iks * xmpp_pubsub_iq_create ( struct ast_xmpp_client client,
const char *  type 
)
static

Create an IQ packet.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
typethe type of IQ packet to create
Returns
iks *

Definition at line 1045 of file res_xmpp.c.

1046{
1048 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1049 iks *request;
1050
1051 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
1052 !(request = iks_new("iq"))) {
1053 return NULL;
1054 }
1055
1056 if (!ast_strlen_zero(clientcfg->pubsubnode)) {
1057 iks_insert_attrib(request, "to", clientcfg->pubsubnode);
1058 }
1059
1060 iks_insert_attrib(request, "from", client->jid->full);
1061 iks_insert_attrib(request, "type", type);
1062 ast_xmpp_client_lock(client);
1063 ast_xmpp_increment_mid(client->mid);
1064 iks_insert_attrib(request, "id", client->mid);
1065 ast_xmpp_client_unlock(client);
1066
1067 return request;
1068}

References ao2_cleanup, ao2_global_obj_ref, ast_strlen_zero(), ast_xmpp_client_lock(), ast_xmpp_client_unlock(), ast_xmpp_increment_mid(), globals, ast_xmpp_client::jid, ast_xmpp_client::mid, ast_xmpp_client::name, NULL, RAII_VAR, request(), type, and xmpp_config_find().

Referenced by xmpp_pubsub_build_node_request(), xmpp_pubsub_build_publish_skeleton(), xmpp_pubsub_create_affiliations(), xmpp_pubsub_create_node(), xmpp_pubsub_delete_node(), xmpp_pubsub_handle_error(), xmpp_pubsub_subscribe(), and xmpp_pubsub_unsubscribe().

◆ xmpp_pubsub_mwi_cb()

static void xmpp_pubsub_mwi_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Callback function for MWI events.

Parameters
datavoid pointer to ast_client structure
sub,msg

Definition at line 1335 of file res_xmpp.c.

1336{
1337 struct ast_xmpp_client *client = data;
1338 char oldmsgs[10], newmsgs[10];
1339 struct ast_mwi_state *mwi_state;
1340
1342 return;
1343 }
1344
1345 mwi_state = stasis_message_data(msg);
1346
1347 if (ast_eid_cmp(&ast_eid_default, &mwi_state->eid)) {
1348 /* If the event didn't originate from this server, don't send it back out. */
1349 return;
1350 }
1351
1352 snprintf(oldmsgs, sizeof(oldmsgs), "%d", mwi_state->old_msgs);
1353 snprintf(newmsgs, sizeof(newmsgs), "%d", mwi_state->new_msgs);
1354 xmpp_pubsub_publish_mwi(client, mwi_state->uniqueid, oldmsgs, newmsgs);
1355}
static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *mailbox, const char *oldmsgs, const char *newmsgs)
Publish MWI to a PubSub node.
Definition: res_xmpp.c:1269
The structure that contains MWI state.
Definition: mwi.h:455
int old_msgs
Definition: mwi.h:460
int new_msgs
Definition: mwi.h:459
const ast_string_field uniqueid
Definition: mwi.h:458
struct ast_eid eid
Definition: mwi.h:463

References ast_eid_cmp(), ast_eid_default, ast_mwi_state_type(), ast_mwi_state::eid, ast_mwi_state::new_msgs, ast_mwi_state::old_msgs, stasis_message_data(), stasis_message_type(), stasis_subscription_is_subscribed(), sub, ast_mwi_state::uniqueid, and xmpp_pubsub_publish_mwi().

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_publish_device_state()

static void xmpp_pubsub_publish_device_state ( struct ast_xmpp_client client,
const char *  device,
const char *  device_state,
unsigned int  cachable 
)
static

Publish device state to a PubSub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
devicethe name of the device whose state to publish
device_statethe state to publish
cachable

Definition at line 1300 of file res_xmpp.c.

1302{
1304 iks *request, *state;
1305 char eid_str[20], cachable_str[2];
1306
1307 if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state", cachable))) {
1308 return;
1309 }
1310
1311 if (ast_test_flag(&cfg->global->pubsub, XMPP_PUBSUB_AUTOCREATE)) {
1312 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1313 xmpp_pubsub_create_node(client, "leaf", device, "device_state");
1314 } else {
1315 xmpp_pubsub_create_node(client, NULL, device, NULL);
1316 }
1317 }
1318
1319 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
1320 state = iks_insert(request, "state");
1321 iks_insert_attrib(state, "xmlns", "http://asterisk.org");
1322 iks_insert_attrib(state, "eid", eid_str);
1323 snprintf(cachable_str, sizeof(cachable_str), "%u", cachable);
1324 iks_insert_attrib(state, "cachable", cachable_str);
1325 iks_insert_cdata(state, device_state, strlen(device_state));
1326 ast_xmpp_client_send(client, iks_root(request));
1327 iks_delete(request);
1328}
static iks * xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, const char *node, const char *event_type, unsigned int cachable)
Build the skeleton of a publish.
Definition: res_xmpp.c:1077
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839

References ao2_cleanup, ao2_global_obj_ref, ast_eid_default, ast_eid_to_str(), ast_test_flag, ast_xmpp_client_send(), globals, NULL, RAII_VAR, request(), state, XMPP_PUBSUB_AUTOCREATE, xmpp_pubsub_build_publish_skeleton(), xmpp_pubsub_create_node(), and XMPP_XEP0248.

Referenced by xmpp_pubsub_devstate_cb().

◆ xmpp_pubsub_publish_mwi()

static void xmpp_pubsub_publish_mwi ( struct ast_xmpp_client client,
const char *  mailbox,
const char *  oldmsgs,
const char *  newmsgs 
)
static

Publish MWI to a PubSub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
mailboxThe mailbox identifier
oldmsgsOld messages
newmsgsNew Messages

Definition at line 1269 of file res_xmpp.c.

1271{
1272 char eid_str[20];
1273 iks *mailbox_node, *request;
1274
1275 request = xmpp_pubsub_build_publish_skeleton(client, mailbox, "message_waiting",
1277 if (!request) {
1278 return;
1279 }
1280
1281 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
1282 mailbox_node = iks_insert(request, "mailbox");
1283 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org");
1284 iks_insert_attrib(mailbox_node, "eid", eid_str);
1285 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs));
1286 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs));
1287
1288 ast_xmpp_client_send(client, iks_root(request));
1289
1290 iks_delete(request);
1291}

References AST_DEVSTATE_CACHABLE, ast_eid_default, ast_eid_to_str(), ast_xmpp_client_send(), voicemailpwcheck::mailbox, request(), and xmpp_pubsub_build_publish_skeleton().

Referenced by xmpp_pubsub_mwi_cb().

◆ xmpp_pubsub_purge_nodes()

static void xmpp_pubsub_purge_nodes ( struct ast_xmpp_client client,
const char *  collection_name 
)
static

Definition at line 4117 of file res_xmpp.c.

4118{
4119 iks *request = xmpp_pubsub_build_node_request(client, collection_name);
4121 iks_filter_add_rule(client->filter, xmpp_pubsub_delete_node_list, client, IKS_RULE_TYPE,
4122 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid,
4123 IKS_RULE_DONE);
4125 iks_delete(request);
4126}
static iks * xmpp_pubsub_build_node_request(struct ast_xmpp_client *client, const char *collection)
Build the a node request.
Definition: res_xmpp.c:3974
static int xmpp_pubsub_delete_node_list(void *data, ikspak *pak)
Delete pubsub item lists.
Definition: res_xmpp.c:4096

References ast_xmpp_client_send(), ast_xmpp_client::filter, ast_xmpp_client::mid, request(), xmpp_pubsub_build_node_request(), and xmpp_pubsub_delete_node_list().

Referenced by xmpp_cli_purge_pubsub_nodes().

◆ xmpp_pubsub_receive_node_list()

static int xmpp_pubsub_receive_node_list ( void *  data,
ikspak *  pak 
)
static

Receive pubsub item lists.

Parameters
datapointer to ast_xmpp_client structure
pakresponse from pubsub diso::items query
Return values
IKS_FILTER_EAT

Definition at line 3998 of file res_xmpp.c.

3999{
4000 struct ast_xmpp_client *client = data;
4001 iks *item = NULL;
4002
4003 if (iks_has_children(pak->query)) {
4004 item = iks_first_tag(pak->query);
4005 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial,
4006 iks_find_attrib(item, "node"));
4007 while ((item = iks_next_tag(item))) {
4008 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node"));
4009 }
4010 }
4011
4012 if (item) {
4013 iks_delete(item);
4014 }
4015
4016
4017 return IKS_FILTER_EAT;
4018}

References ast_verbose(), item, ast_xmpp_client::jid, ast_xmpp_client::name, and NULL.

Referenced by xmpp_pubsub_request_nodes().

◆ xmpp_pubsub_request_nodes()

static void xmpp_pubsub_request_nodes ( struct ast_xmpp_client client,
const char *  collection 
)
static

Request item list from pubsub.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
collectionname of the collection for request

Definition at line 4025 of file res_xmpp.c.

4026{
4027 iks *request = xmpp_pubsub_build_node_request(client, collection);
4028
4029 if (!request) {
4030 ast_log(LOG_ERROR, "Could not request pubsub nodes on client '%s' - IQ could not be created\n", client->name);
4031 return;
4032 }
4033
4034 iks_filter_add_rule(client->filter, xmpp_pubsub_receive_node_list, client, IKS_RULE_TYPE,
4035 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid,
4036 IKS_RULE_DONE);
4038 iks_delete(request);
4039
4040}
static int xmpp_pubsub_receive_node_list(void *data, ikspak *pak)
Receive pubsub item lists.
Definition: res_xmpp.c:3998

References ast_log, ast_xmpp_client_send(), ast_xmpp_client::filter, LOG_ERROR, ast_xmpp_client::mid, ast_xmpp_client::name, request(), xmpp_pubsub_build_node_request(), and xmpp_pubsub_receive_node_list().

Referenced by xmpp_cli_list_pubsub_nodes().

◆ xmpp_pubsub_subscribe()

static void xmpp_pubsub_subscribe ( struct ast_xmpp_client client,
const char *  node 
)
static

Subscribe to a PubSub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
nodethe name of the node to which to subscribe

Definition at line 1410 of file res_xmpp.c.

1411{
1413 iks *request = xmpp_pubsub_iq_create(client, "set");
1414 iks *pubsub, *subscribe;
1415
1416 if (!cfg || !cfg->global || !request) {
1417 ast_log(LOG_ERROR, "Could not create IQ when creating pubsub subscription on client '%s'\n", client->name);
1418 return;
1419 }
1420
1421 pubsub = iks_insert(request, "pubsub");
1422 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1423 subscribe = iks_insert(pubsub, "subscribe");
1424 iks_insert_attrib(subscribe, "jid", client->jid->partial);
1425 iks_insert_attrib(subscribe, "node", node);
1426 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1427 iks *options, *x, *sub_options, *sub_type, *sub_depth, *sub_expire;
1428 options = iks_insert(pubsub, "options");
1429 x = iks_insert(options, "x");
1430 iks_insert_attrib(x, "xmlns", "jabber:x:data");
1431 iks_insert_attrib(x, "type", "submit");
1432 sub_options = iks_insert(x, "field");
1433 iks_insert_attrib(sub_options, "var", "FORM_TYPE");
1434 iks_insert_attrib(sub_options, "type", "hidden");
1435 iks_insert_cdata(iks_insert(sub_options, "value"),
1436 "http://jabber.org/protocol/pubsub#subscribe_options", 51);
1437 sub_type = iks_insert(x, "field");
1438 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type");
1439 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5);
1440 sub_depth = iks_insert(x, "field");
1441 iks_insert_attrib(sub_depth, "var", "pubsub#subscription_depth");
1442 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3);
1443 sub_expire = iks_insert(x, "field");
1444 iks_insert_attrib(sub_expire, "var", "pubsub#expire");
1445 iks_insert_cdata(iks_insert(sub_expire, "value"), "presence", 8);
1446 }
1448 iks_delete(request);
1449}
unsigned char subscribe
Definition: res_corosync.c:243

References ao2_cleanup, ao2_global_obj_ref, ast_log, ast_test_flag, ast_xmpp_client_send(), globals, ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::name, options, RAII_VAR, request(), subscribe, xmpp_pubsub_iq_create(), and XMPP_XEP0248.

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_unsubscribe()

static void xmpp_pubsub_unsubscribe ( struct ast_xmpp_client client,
const char *  node 
)
static

Unsubscribe from a PubSub node.

Parameters
clientthe configured XMPP client we use to connect to a XMPP server
nodethe name of the node to which to unsubscribe from

Definition at line 1385 of file res_xmpp.c.

1386{
1387 iks *request = xmpp_pubsub_iq_create(client, "set");
1388 iks *pubsub, *unsubscribe;
1389
1390 if (!request) {
1391 ast_log(LOG_ERROR, "Could not create IQ when creating pubsub unsubscription on client '%s'\n", client->name);
1392 return;
1393 }
1394
1395 pubsub = iks_insert(request, "pubsub");
1396 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1397 unsubscribe = iks_insert(pubsub, "unsubscribe");
1398 iks_insert_attrib(unsubscribe, "jid", client->jid->partial);
1399 iks_insert_attrib(unsubscribe, "node", node);
1400
1402 iks_delete(request);
1403}
static int unsubscribe(void *obj, void *arg, int flags)

References ast_log, ast_xmpp_client_send(), ast_xmpp_client::jid, LOG_ERROR, ast_xmpp_client::name, request(), unsubscribe(), and xmpp_pubsub_iq_create().

Referenced by ast_xmpp_client_disconnect(), and xmpp_init_event_distribution().

◆ xmpp_resource_cmp()

static int xmpp_resource_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Comparator function for XMPP resource.

Definition at line 853 of file res_xmpp.c.

854{
855 struct ast_xmpp_resource *resource1 = obj;
856 const char *resource = arg;
857
858 return !strcmp(resource1->resource, resource) ? CMP_MATCH | CMP_STOP : 0;
859}

References CMP_MATCH, CMP_STOP, and ast_xmpp_resource::resource.

Referenced by get_buddy_status(), xmpp_client_create_buddy(), xmpp_client_service_discovery_result_hook(), and xmpp_pak_presence().

◆ xmpp_resource_destructor()

static void xmpp_resource_destructor ( void *  obj)
static

Destructor callback function for XMPP resource.

Definition at line 835 of file res_xmpp.c.

836{
837 struct ast_xmpp_resource *resource = obj;
838
839 if (resource->description) {
840 ast_free(resource->description);
841 }
842}

References ast_free, and ast_xmpp_resource::resource.

Referenced by xmpp_pak_presence().

◆ xmpp_resource_hash()

static int xmpp_resource_hash ( const void *  obj,
const int  flags 
)
static

Hashing function for XMPP resource.

Definition at line 845 of file res_xmpp.c.

846{
847 const struct ast_xmpp_resource *resource = obj;
848
849 return flags & OBJ_KEY ? -1 : resource->priority;
850}

References OBJ_KEY, and ast_xmpp_resource::resource.

Referenced by xmpp_client_create_buddy().

◆ xmpp_resource_immediate()

static int xmpp_resource_immediate ( void *  obj,
void *  arg,
int  flags 
)
static

Internal astobj2 callback function which returns the first resource, which is the highest priority one.

Definition at line 1622 of file res_xmpp.c.

1623{
1624 return CMP_MATCH | CMP_STOP;
1625}

References CMP_MATCH, and CMP_STOP.

Referenced by get_buddy_status().

◆ xmpp_resource_is_available()

static int xmpp_resource_is_available ( void *  obj,
void *  arg,
int  flags 
)
static

Callback function which returns when the resource is available.

Definition at line 3221 of file res_xmpp.c.

3222{
3223 struct ast_xmpp_resource *resource = obj;
3224
3225 return (resource->status == IKS_SHOW_AVAILABLE) ? CMP_MATCH | CMP_STOP : 0;
3226}

References CMP_MATCH, CMP_STOP, and ast_xmpp_resource::resource.

Referenced by xmpp_pak_presence().

◆ xmpp_roster_hook()

static int xmpp_roster_hook ( void *  data,
ikspak *  pak 
)
static

Hook function called when roster is received from server.

Definition at line 2247 of file res_xmpp.c.

2248{
2250 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2251 struct ast_xmpp_client *client = data;
2252 iks *item;
2253
2254 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
2255 return IKS_FILTER_EAT;
2256 }
2257
2258 for (item = iks_child(pak->query); item; item = iks_next(item)) {
2259 struct ast_xmpp_buddy *buddy;
2260
2261 if (iks_strcmp(iks_name(item), "item")) {
2262 continue;
2263 }
2264
2265 if (!(buddy = ao2_find(client->buddies, iks_find_attrib(item, "jid"), OBJ_KEY))) {
2266 if (ast_test_flag(&clientcfg->flags, XMPP_AUTOPRUNE)) {
2267 /* The buddy has not been specified in the configuration file, we no longer
2268 * want them on our buddy list or to receive their presence. */
2269 if (xmpp_client_unsubscribe_user(client, iks_find_attrib(item, "jid"))) {
2270 ast_log(LOG_ERROR, "Could not unsubscribe user '%s' on client '%s'\n",
2271 iks_find_attrib(item, "jid"), client->name);
2272 }
2273 continue;
2274 }
2275
2276 if (!(buddy = xmpp_client_create_buddy(client->buddies, iks_find_attrib(item, "jid")))) {
2277 ast_log(LOG_ERROR, "Could not allocate buddy '%s' on client '%s'\n", iks_find_attrib(item, "jid"),
2278 client->name);
2279 continue;
2280 }
2281 }
2282
2283 /* Determine if we need to subscribe to their presence or not */
2284 if (!iks_strcmp(iks_find_attrib(item, "subscription"), "none") ||
2285 !iks_strcmp(iks_find_attrib(item, "subscription"), "from")) {
2286 buddy->subscribe = 1;
2287 } else {
2288 buddy->subscribe = 0;
2289 }
2290
2291 ao2_ref(buddy, -1);
2292 }
2293
2294 /* If autoregister is enabled we need to go through every buddy that we need to subscribe to and do so */
2295 if (ast_test_flag(&clientcfg->flags, XMPP_AUTOREGISTER)) {
2297 }
2298
2300
2301 return IKS_FILTER_EAT;
2302}
static int xmpp_client_unsubscribe_user(struct ast_xmpp_client *client, const char *user)
Helper function which unsubscribes a user and removes them from the roster.
Definition: res_xmpp.c:2189

References ao2_callback, ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_ref, ast_log, ast_test_flag, ast_xmpp_client::buddies, globals, item, LOG_ERROR, ast_xmpp_client::name, NULL, OBJ_KEY, OBJ_MULTIPLE, OBJ_NODATA, RAII_VAR, ast_xmpp_buddy::subscribe, XMPP_AUTOPRUNE, XMPP_AUTOREGISTER, xmpp_client_change_state(), xmpp_client_create_buddy(), xmpp_client_subscribe_user(), xmpp_client_unsubscribe_user(), xmpp_config_find(), and XMPP_STATE_CONNECTED.

Referenced by xmpp_connect_hook().

◆ xmpp_send_cb()

static int xmpp_send_cb ( const struct ast_msg msg,
const char *  to,
const char *  from 
)
static

Definition at line 2126 of file res_xmpp.c.

2127{
2129 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2130 char *sender, *dest;
2131 int res;
2132
2133 sender = ast_strdupa(from);
2134 strsep(&sender, ":");
2135 dest = ast_strdupa(to);
2136 strsep(&dest, ":");
2137
2138 if (ast_strlen_zero(sender)) {
2139 ast_log(LOG_ERROR, "MESSAGE(from) of '%s' invalid for XMPP\n", from);
2140 return -1;
2141 }
2142
2143 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, sender))) {
2144 ast_log(LOG_WARNING, "Could not finder account to send from as '%s'\n", sender);
2145 return -1;
2146 }
2147
2148 ast_debug(1, "Sending message to '%s' from '%s'\n", dest, clientcfg->name);
2149
2150 if ((res = ast_xmpp_client_send_message(clientcfg->client, dest, ast_msg_get_body(msg))) != IKS_OK) {
2151 ast_log(LOG_WARNING, "Failed to send XMPP message (%d).\n", res);
2152 }
2153
2154 return res == IKS_OK ? 0 : -1;
2155}
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: main/message.c:545

References ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_log, ast_msg_get_body(), ast_strdupa, ast_strlen_zero(), ast_xmpp_client_send_message(), ast_xmpp_message::from, globals, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, strsep(), and xmpp_config_find().

◆ xmpp_send_exec()

static int xmpp_send_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1838 of file res_xmpp.c.

1839{
1841 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1842 char *s;
1844 AST_APP_ARG(sender);
1845 AST_APP_ARG(recipient);
1847 );
1848
1849 if (ast_strlen_zero(data)) {
1850 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
1851 return -1;
1852 }
1853 s = ast_strdupa(data);
1854
1856
1857 if ((args.argc < 3) || ast_strlen_zero(args.message) || !strchr(args.recipient, '@')) {
1858 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
1859 return -1;
1860 }
1861
1862 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1863 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
1864 return -1;
1865 }
1866
1867 ast_xmpp_client_send_message(clientcfg->client, args.recipient, args.message);
1868
1869 return 0;
1870}

References ao2_cleanup, ao2_global_obj_ref, app_ajisend, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_xmpp_client_send_message(), globals, LOG_WARNING, NULL, RAII_VAR, and xmpp_config_find().

Referenced by load_module().

◆ xmpp_send_stream_header()

static int xmpp_send_stream_header ( struct ast_xmpp_client client,
const struct ast_xmpp_client_config cfg,
const char *  to 
)
static

Helper function which sends an XMPP stream header to the server.

Definition at line 2522 of file res_xmpp.c.

2523{
2524 char *namespace = ast_test_flag(&cfg->flags, XMPP_COMPONENT) ? "jabber:component:accept" : "jabber:client";
2525 char msg[91 + strlen(namespace) + 6 + strlen(to) + 16 + 1];
2526
2527 snprintf(msg, sizeof(msg), "<?xml version='1.0'?>"
2528 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='"
2529 "%s' to='%s' version='1.0'>", namespace, to);
2530
2531 return xmpp_client_send_raw_message(client, msg);
2532}

References ast_test_flag, ast_xmpp_client_config::flags, xmpp_client_send_raw_message(), and XMPP_COMPONENT.

Referenced by xmpp_client_authenticating(), and xmpp_client_requested_tls().

◆ xmpp_sendgroup_exec()

static int xmpp_sendgroup_exec ( struct ast_channel chan,
const char *  data 
)
static

Application to send a message to a groupchat.

Parameters
chanast_channel
dataData is sender|groupchat|message.
Return values
0success
-1error

Definition at line 1879 of file res_xmpp.c.

1880{
1882 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1883 char *s, nick[XMPP_MAX_RESJIDLEN];
1885 AST_APP_ARG(sender);
1886 AST_APP_ARG(groupchat);
1888 AST_APP_ARG(nick);
1889 );
1890
1891 if (ast_strlen_zero(data)) {
1892 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
1893 return -1;
1894 }
1895 s = ast_strdupa(data);
1896
1898 if ((args.argc < 3) || (args.argc > 4) || ast_strlen_zero(args.message) || !strchr(args.groupchat, '@')) {
1899 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
1900 return -1;
1901 }
1902
1903 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1904 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
1905 return -1;
1906 }
1907
1908 if (ast_strlen_zero(args.nick) || args.argc == 3) {
1909 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1910 snprintf(nick, sizeof(nick), "asterisk");
1911 } else {
1912 snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
1913 }
1914 } else {
1915 snprintf(nick, sizeof(nick), "%s", args.nick);
1916 }
1917
1918 ast_xmpp_chatroom_send(clientcfg->client, nick, args.groupchat, args.message);
1919
1920 return 0;
1921}
int ast_xmpp_chatroom_send(struct ast_xmpp_client *client, const char *nickname, const char *address, const char *message)
Send a message to an XMPP multi-user chatroom.
Definition: res_xmpp.c:1015

References ao2_cleanup, ao2_global_obj_ref, app_ajisendgroup, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_xmpp_chatroom_send(), globals, LOG_ERROR, NULL, RAII_VAR, XMPP_COMPONENT, xmpp_config_find(), and XMPP_MAX_RESJIDLEN.

Referenced by load_module().

◆ xmpp_show_buddies()

static char * xmpp_show_buddies ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4410 of file res_xmpp.c.

4411{
4413 struct ao2_iterator i;
4414 struct ast_xmpp_client_config *clientcfg;
4415
4416 switch (cmd) {
4417 case CLI_INIT:
4418 e->command = "xmpp show buddies";
4419 e->usage =
4420 "Usage: xmpp show buddies\n"
4421 " Shows buddy lists of our clients\n";
4422 return NULL;
4423 case CLI_GENERATE:
4424 return NULL;
4425 }
4426
4427 if (!cfg || !cfg->clients) {
4428 return NULL;
4429 }
4430
4431 ast_cli(a->fd, "XMPP buddy lists\n");
4432
4433 i = ao2_iterator_init(cfg->clients, 0);
4434 while ((clientcfg = ao2_iterator_next(&i))) {
4435 struct ao2_iterator bud;
4436 struct ast_xmpp_buddy *buddy;
4437
4438 ast_cli(a->fd, "Client: %s\n", clientcfg->name);
4439
4440 bud = ao2_iterator_init(clientcfg->client->buddies, 0);
4441 while ((buddy = ao2_iterator_next(&bud))) {
4442 struct ao2_iterator res;
4444
4445 ast_cli(a->fd, "\tBuddy:\t%s\n", buddy->id);
4446
4447 res = ao2_iterator_init(buddy->resources, 0);
4448 while ((resource = ao2_iterator_next(&res))) {
4449 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource);
4450 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->caps.node);
4451 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->caps.version);
4452 ast_cli(a->fd, "\t\t\tGoogle Talk capable: %s\n", resource->caps.google ? "yes" : "no");
4453 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->caps.jingle ? "yes" : "no");
4454
4455 ao2_ref(resource, -1);
4456 }
4458
4459 ao2_ref(buddy, -1);
4460 }
4462
4463 ao2_ref(clientcfg, -1);
4464 }
4466
4467 return CLI_SUCCESS;
4468}

References a, ao2_cleanup, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), ast_xmpp_client::buddies, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_xmpp_client_config::client, ast_cli_entry::command, globals, ast_xmpp_buddy::id, ast_xmpp_client_config::name, NULL, RAII_VAR, ast_xmpp_resource::resource, ast_xmpp_buddy::resources, and ast_cli_entry::usage.

◆ xmpp_show_clients()

static char * xmpp_show_clients ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4334 of file res_xmpp.c.

4335{
4337 struct ao2_iterator i;
4338 struct ast_xmpp_client_config *clientcfg;
4339
4340 switch (cmd) {
4341 case CLI_INIT:
4342 e->command = "xmpp show connections";
4343 e->usage =
4344 "Usage: xmpp show connections\n"
4345 " Shows state of client and component connections\n";
4346 return NULL;
4347 case CLI_GENERATE:
4348 return NULL;
4349 }
4350
4351 if (!cfg || !cfg->clients) {
4352 return NULL;
4353 }
4354
4355 ast_cli(a->fd, "Jabber Users and their status:\n");
4356
4357 i = ao2_iterator_init(cfg->clients, 0);
4358 while ((clientcfg = ao2_iterator_next(&i))) {
4359 char *state;
4360
4361 switch (clientcfg->client->state) {
4363 state = "Disconnecting";
4364 break;
4366 state = "Disconnected";
4367 break;
4369 state = "Connecting";
4370 break;
4372 state = "Waiting to request TLS";
4373 break;
4375 state = "Requested TLS";
4376 break;
4378 state = "Waiting to authenticate";
4379 break;
4381 state = "Authenticating";
4382 break;
4383 case XMPP_STATE_ROSTER:
4384 state = "Retrieving roster";
4385 break;
4387 state = "Connected";
4388 break;
4389 default:
4390 state = "Unknown";
4391 }
4392
4393 ast_cli(a->fd, " [%s] %s - %s\n", clientcfg->name, clientcfg->user, state);
4394
4395 ao2_ref(clientcfg, -1);
4396 }
4398
4399 ast_cli(a->fd, "----\n");
4400 ast_cli(a->fd, " Number of clients: %d\n", ao2_container_count(cfg->clients));
4401
4402 return CLI_SUCCESS;
4403}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
@ XMPP_STATE_CONNECTING
Definition: xmpp.h:74

References a, ao2_cleanup, ao2_container_count(), ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_xmpp_client_config::client, ast_cli_entry::command, globals, ast_xmpp_client_config::name, NULL, RAII_VAR, ast_xmpp_client::state, state, ast_cli_entry::usage, ast_xmpp_client_config::user, XMPP_STATE_AUTHENTICATE, XMPP_STATE_AUTHENTICATING, XMPP_STATE_CONNECTED, XMPP_STATE_CONNECTING, XMPP_STATE_DISCONNECTED, XMPP_STATE_DISCONNECTING, XMPP_STATE_REQUEST_TLS, XMPP_STATE_REQUESTED_TLS, and XMPP_STATE_ROSTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk XMPP 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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static

Definition at line 4703 of file res_xmpp.c.

◆ app_ajijoin

const char* app_ajijoin = "JabberJoin"
static

Definition at line 519 of file res_xmpp.c.

Referenced by load_module(), unload_module(), and xmpp_join_exec().

◆ app_ajileave

const char* app_ajileave = "JabberLeave"
static

Definition at line 520 of file res_xmpp.c.

Referenced by load_module(), unload_module(), and xmpp_leave_exec().

◆ app_ajisend

const char* app_ajisend = "JabberSend"
static

Definition at line 516 of file res_xmpp.c.

Referenced by load_module(), unload_module(), and xmpp_send_exec().

◆ app_ajisendgroup

const char* app_ajisendgroup = "JabberSendGroup"
static

Definition at line 517 of file res_xmpp.c.

Referenced by load_module(), unload_module(), and xmpp_sendgroup_exec().

◆ app_ajistatus

const char* app_ajistatus = "JabberStatus"
static

Definition at line 518 of file res_xmpp.c.

Referenced by unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4703 of file res_xmpp.c.

◆ client_option

struct aco_type client_option
static

Definition at line 810 of file res_xmpp.c.

◆ client_options

struct aco_type* client_options[] = ACO_TYPES(&client_option)

Definition at line 821 of file res_xmpp.c.

Referenced by load_module().

◆ debug

int debug
static

◆ global_option

struct aco_type global_option
static

Definition at line 800 of file res_xmpp.c.

◆ global_options

struct aco_type* global_options[] = ACO_TYPES(&global_option)

Definition at line 808 of file res_xmpp.c.

Referenced by load_module().

◆ jabberreceive_function

struct ast_custom_function jabberreceive_function
static
Initial value:
= {
.name = "JABBER_RECEIVE",
}
static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
Definition: res_xmpp.c:1933

Definition at line 2079 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ jabberstatus_function

struct ast_custom_function jabberstatus_function
static
Initial value:
= {
.name = "JABBER_STATUS",
}
static int acf_jabberstatus_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
Definition: res_xmpp.c:1666

Definition at line 1706 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ message_received_condition

ast_cond_t message_received_condition
static

Definition at line 522 of file res_xmpp.c.

Referenced by acf_jabberreceive_read(), load_module(), unload_module(), and xmpp_pak_message().

◆ messagelock

ast_mutex_t messagelock
static

Definition at line 523 of file res_xmpp.c.

Referenced by acf_jabberreceive_read(), load_module(), unload_module(), and xmpp_pak_message().

◆ msg_tech

const struct ast_msg_tech msg_tech
static
Initial value:
= {
.name = "xmpp",
.msg_send = xmpp_send_cb,
}
static int xmpp_send_cb(const struct ast_msg *msg, const char *to, const char *from)
Definition: res_xmpp.c:2126

Definition at line 2157 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ res_xmpp_conf

struct aco_file res_xmpp_conf
Initial value:
= {
.filename = "xmpp.conf",
.alias = "jabber.conf",
}
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static struct aco_type client_option
Definition: res_xmpp.c:810
static struct aco_type global_option
Definition: res_xmpp.c:800

Definition at line 823 of file res_xmpp.c.

◆ xmpp_cli

struct ast_cli_entry xmpp_cli[]
static

Definition at line 4470 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ xmpp_pak_handlers

const struct xmpp_pak_handler xmpp_pak_handlers[]
static
Initial value:
= {
{ IKS_PAK_MESSAGE, xmpp_pak_message, },
{ IKS_PAK_PRESENCE, xmpp_pak_presence, },
{ IKS_PAK_S10N, xmpp_pak_s10n, },
}
static int xmpp_pak_s10n(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Internal function called when a subscription message is received.
Definition: res_xmpp.c:3392
static int xmpp_pak_message(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Internal function called when a message is received.
Definition: res_xmpp.c:3117
static int xmpp_pak_presence(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Internal function called when a presence message is received.
Definition: res_xmpp.c:3263

Referenced by xmpp_action_hook().

◆ xmpp_state_handlers

const struct xmpp_state_handler xmpp_state_handlers[]
static

Referenced by xmpp_action_hook().