Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1844
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
const char * ast_channel_name(const struct ast_channel *chan)
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:204
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
static void * xmpp_config_find(struct ao2_container *tmp_container, const char *category)
Find function for configuration.
Definition: res_xmpp.c:657
static ast_mutex_t messagelock
Definition: res_xmpp.c:523
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:406
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:71
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:105
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:157
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:233
#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:936
#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, parse(), 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  }
1683  AST_STANDARD_APP_ARGS(args, data);
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);
956  ast_xmpp_increment_mid(client->mid);
957  ast_xmpp_client_unlock(client);
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 
966 done:
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
static void * xmpp_client_find_or_create(const char *category)
Look up existing client or create a new one.
Definition: res_xmpp.c:663
#define BUDDY_BUCKETS
Number of buckets for buddies (per client)
Definition: res_xmpp.c:429
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:1136
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(), 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")) {
4542  ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_KEEPALIVE);
4543  } else if (!strcasecmp(var->name, "autoprune")) {
4544  ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_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:614
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
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::@320 messages
const ast_string_field name
Definition: xmpp.h:123
struct ast_xmpp_message::@319 list
char * from
Definition: xmpp.h:102

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_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
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:546
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:849
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)) {
4622  return AST_MODULE_LOAD_DECLINE;
4623  }
4624 
4626  aco_option_register_custom(&cfg_info, "autoprune", ACO_EXACT, global_options, "no", global_bitfield_handler, 0);
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));
4637  aco_option_register(&cfg_info, "serverhost", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, server));
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));
4641  aco_option_register(&cfg_info, "priority", ACO_EXACT, client_options, "1", OPT_UINT_T, 0, FLDSET(struct ast_xmpp_client_config, priority));
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);
4656  aco_option_register_custom(&cfg_info, "keepalive", ACO_EXACT, client_options, "yes", 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);
4663  return AST_MODULE_LOAD_DECLINE;
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 
4685  return AST_MODULE_LOAD_SUCCESS;
4686 }
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
#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:199
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#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:1543
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: main/utils.c:2995
#define ARRAY_LEN(a)
Definition: utils.h:661
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(), 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:3166
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3198
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3087
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:2827
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) {
4691  return AST_MODULE_LOAD_DECLINE;
4692  }
4693 
4694  return 0;
4695 }

◆ 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:226

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:7268
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ast_mutex_destroy(a)
Definition: lock.h:186
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:1237

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 
618  AST_LIST_HEAD_INIT(&client->messages);
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 
647  ast_string_field_set(client, name, name);
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: main/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 char base64[64]
Definition: main/utils.c:80
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
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: main/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 sip_cc_notify_state state
Definition: chan_sip.c:966
@ 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, state, ast_xmpp_client::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 */
3909  if (ast_test_flag(&cfg->flags, XMPP_AUTOREGISTER)) {
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_thread(void *data)
XMPP client connection thread.
Definition: res_xmpp.c:3728
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 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:587
#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.

◆ 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;
554  struct ast_xmpp_message *message;
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 
2644 failure:
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 
2387 end:
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;
2407  struct ast_xmpp_resource *resource;
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 
2418  ao2_lock(resource);
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 
1003 done:
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 
2336 done:
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 
2217 done:
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 
2981 done:
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 
3030 done:
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 
2915 done:
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:3698

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 
3080 done:
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;
743 error:
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:2312

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

◆ 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:868
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_DISTRIBUTE_EVENTS, xmpp_init_event_distribution(), xmpp_roster_hook(), and XMPP_STATE_ROSTER.

Referenced by xmpp_client_authenticate_digest(), and xmpp_client_authenticating().

◆ 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 
1596  if (!(client->mwi_sub = stasis_subscribe_pool(ast_mwi_topic_all(), xmpp_pubsub_mwi_cb, client))) {
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_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
struct stasis_topic * ast_mwi_topic_all(void)
Get the Stasis Message Bus API topic for MWI messages.
Definition: mwi.c:89
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
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 stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:973
@ 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:1025
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:1079
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:680
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
#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 (