Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 558 of file res_xmpp.c.

◆ BUDDY_NOT_IN_ROSTER

#define BUDDY_NOT_IN_ROSTER   7

Definition at line 1757 of file res_xmpp.c.

◆ BUDDY_OFFLINE

#define BUDDY_OFFLINE   6

Definition at line 1756 of file res_xmpp.c.

◆ CLIENT_BUCKETS

#define CLIENT_BUCKETS   53

Number of buckets for client connections.

Definition at line 555 of file res_xmpp.c.

◆ RESOURCE_BUCKETS

#define RESOURCE_BUCKETS   53

Number of buckets for resources (per buddy)

Definition at line 561 of file res_xmpp.c.

◆ STATUS_DISAPPEAR

#define STATUS_DISAPPEAR   6

Status for a disappearing buddy.

Definition at line 567 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 564 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 533 of file res_xmpp.c.

533 {
534 XMPP_AUTOPRUNE = (1 << 0),
535 XMPP_AUTOREGISTER = (1 << 1),
536 XMPP_AUTOACCEPT = (1 << 2),
537 XMPP_DEBUG = (1 << 3),
538 XMPP_USETLS = (1 << 4),
539 XMPP_USESASL = (1 << 5),
540 XMPP_FORCESSL = (1 << 6),
541 XMPP_KEEPALIVE = (1 << 7),
542 XMPP_COMPONENT = (1 << 8),
543 XMPP_SEND_TO_DIALPLAN = (1 << 9),
544 XMPP_DISTRIBUTE_EVENTS = (1 << 10),
545};
@ XMPP_AUTOREGISTER
Definition: res_xmpp.c:535
@ XMPP_DISTRIBUTE_EVENTS
Definition: res_xmpp.c:544
@ XMPP_USETLS
Definition: res_xmpp.c:538
@ XMPP_AUTOPRUNE
Definition: res_xmpp.c:534
@ XMPP_FORCESSL
Definition: res_xmpp.c:540
@ XMPP_USESASL
Definition: res_xmpp.c:539
@ XMPP_AUTOACCEPT
Definition: res_xmpp.c:536
@ XMPP_DEBUG
Definition: res_xmpp.c:537
@ XMPP_KEEPALIVE
Definition: res_xmpp.c:541
@ XMPP_COMPONENT
Definition: res_xmpp.c:542
@ XMPP_SEND_TO_DIALPLAN
Definition: res_xmpp.c:543

◆ anonymous enum

anonymous enum

Supported pubsub configuration flags.

Enumerator
XMPP_XEP0248 
XMPP_PUBSUB 
XMPP_PUBSUB_AUTOCREATE 

Definition at line 548 of file res_xmpp.c.

548 {
549 XMPP_XEP0248 = (1 << 0),
550 XMPP_PUBSUB = (1 << 1),
551 XMPP_PUBSUB_AUTOCREATE = (1 << 2),
552};
@ XMPP_XEP0248
Definition: res_xmpp.c:549
@ XMPP_PUBSUB
Definition: res_xmpp.c:550
@ XMPP_PUBSUB_AUTOCREATE
Definition: res_xmpp.c:551

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4832 of file res_xmpp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4832 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 2062 of file res_xmpp.c.

2063{
2065 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2066 char *parse = NULL;
2067 int timeout, jidlen, resourcelen, found = 0;
2068 struct timeval start;
2069 long diff = 0;
2070 struct ast_xmpp_message *message;
2072 AST_APP_ARG(account);
2073 AST_APP_ARG(jid);
2074 AST_APP_ARG(timeout);
2075 );
2077 AST_APP_ARG(screenname);
2078 AST_APP_ARG(resource);
2079 );
2080
2081 if (ast_strlen_zero(data)) {
2082 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
2083 return -1;
2084 }
2085
2086 parse = ast_strdupa(data);
2088
2089 if (args.argc < 2 || args.argc > 3) {
2090 ast_log(LOG_WARNING, "%s requires arguments (account,jid[,timeout])\n", name);
2091 return -1;
2092 }
2093
2094 parse = ast_strdupa(args.jid);
2095 AST_NONSTANDARD_APP_ARGS(jid, parse, '/');
2096 if (jid.argc < 1 || jid.argc > 2 || strlen(args.jid) > XMPP_MAX_JIDLEN) {
2097 ast_log(LOG_WARNING, "Invalid JID : %s\n", parse);
2098 return -1;
2099 }
2100
2101 if (ast_strlen_zero(args.timeout)) {
2102 timeout = 20;
2103 } else {
2104 sscanf(args.timeout, "%d", &timeout);
2105 if (timeout <= 0) {
2106 ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
2107 return -1;
2108 }
2109 }
2110
2111 jidlen = strlen(jid.screenname);
2112 resourcelen = ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource);
2113
2114 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.account))) {
2115 ast_log(LOG_WARNING, "Could not find client %s, exiting\n", args.account);
2116 return -1;
2117 }
2118
2119 ast_debug(3, "Waiting for an XMPP message from %s\n", args.jid);
2120
2121 start = ast_tvnow();
2122
2123 if (chan && ast_autoservice_start(chan) < 0) {
2124 ast_log(LOG_WARNING, "Cannot start autoservice for channel %s\n", ast_channel_name(chan));
2125 return -1;
2126 }
2127
2128 /* search the messages list, grab the first message that matches with
2129 * the from JID we're expecting, and remove it from the messages list */
2130 while (diff < timeout) {
2131 struct timespec ts = { 0, };
2132 struct timeval wait;
2133 int res = 0;
2134
2135 wait = ast_tvadd(start, ast_tv(timeout, 0));
2136 ts.tv_sec = wait.tv_sec;
2137 ts.tv_nsec = wait.tv_usec * 1000;
2138
2139 /* wait up to timeout seconds for an incoming message */
2141 if (AST_LIST_EMPTY(&clientcfg->client->messages)) {
2143 }
2145 if (res == ETIMEDOUT) {
2146 ast_debug(3, "No message received from %s in %d seconds\n", args.jid, timeout);
2147 break;
2148 }
2149
2150 AST_LIST_LOCK(&clientcfg->client->messages);
2151 AST_LIST_TRAVERSE_SAFE_BEGIN(&clientcfg->client->messages, message, list) {
2152 if (jid.argc == 1) {
2153 /* no resource provided, compare bare JIDs */
2154 if (strncasecmp(jid.screenname, message->from, jidlen)) {
2155 continue;
2156 }
2157 } else {
2158 /* resource appended, compare bare JIDs and resources */
2159 char *resource = strchr(message->from, '/');
2160 if (!resource || strlen(resource) == 0) {
2161 ast_log(LOG_WARNING, "Remote JID has no resource : %s\n", message->from);
2162 if (strncasecmp(jid.screenname, message->from, jidlen)) {
2163 continue;
2164 }
2165 } else {
2166 resource ++;
2167 if (strncasecmp(jid.screenname, message->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) {
2168 continue;
2169 }
2170 }
2171 }
2172 /* check if the message is not too old */
2173 if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= clientcfg->message_timeout) {
2174 ast_debug(3, "Found old message from %s, deleting it\n", message->from);
2177 continue;
2178 }
2179 found = 1;
2180 ast_copy_string(buf, message->message, buflen);
2183 break;
2184 }
2186 AST_LIST_UNLOCK(&clientcfg->client->messages);
2187 if (found) {
2188 break;
2189 }
2190
2191 /* check timeout */
2192 diff = ast_tvdiff_ms(ast_tvnow(), start);
2193 }
2194
2195 if (chan && ast_autoservice_stop(chan) < 0) {
2196 ast_log(LOG_WARNING, "Cannot stop autoservice for channel %s\n", ast_channel_name(chan));
2197 }
2198
2199 /* return if we timed out */
2200 if (!found) {
2201 ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid);
2202 return -1;
2203 }
2204
2205 return 0;
2206}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
static struct console_pvt globals
const char * ast_channel_name(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_NOTICE
#define LOG_WARNING
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:213
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_lock(a)
Definition: lock.h:196
static ast_mutex_t messagelock
Definition: res_xmpp.c:652
static void * xmpp_config_find(struct ao2_container *tmp_container, const char *category)
Find function for configuration.
Definition: res_xmpp.c:786
static void xmpp_message_destroy(struct ast_xmpp_message *message)
Destroy function for XMPP messages.
Definition: res_xmpp.c:667
static ast_cond_t message_received_condition
Definition: res_xmpp.c:651
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
XMPP Client Configuration.
Definition: res_xmpp.c:579
XMPP Message.
Definition: xmpp.h:101
char * message
Definition: xmpp.h:103
const char * args
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
Definition: time.h:73
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define XMPP_MAX_JIDLEN
Definition: xmpp.h:62

References ao2_cleanup, ao2_global_obj_ref, args, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_name(), ast_cond_timedwait, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvdiff_sec(), ast_tvnow(), buf, globals, LOG_NOTICE, LOG_WARNING, ast_xmpp_message::message, message_received_condition, messagelock, name, NULL, RAII_VAR, xmpp_config_find(), XMPP_MAX_JIDLEN, and xmpp_message_destroy().

◆ acf_jabberstatus_read()

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

Definition at line 1795 of file res_xmpp.c.

1796{
1798 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1800 AST_APP_ARG(sender);
1801 AST_APP_ARG(jid);
1802 );
1804 AST_APP_ARG(screenname);
1805 AST_APP_ARG(resource);
1806 );
1807
1808 if (ast_strlen_zero(data)) {
1809 ast_log(LOG_ERROR, "Usage: JABBER_STATUS(<sender>,<jid>[/<resource>])\n");
1810 return 0;
1811 }
1813
1814 if (args.argc != 2) {
1815 ast_log(LOG_ERROR, "JABBER_STATUS requires 2 arguments: sender and jid.\n");
1816 return -1;
1817 }
1818
1819 AST_NONSTANDARD_APP_ARGS(jid, args.jid, '/');
1820 if (jid.argc < 1 || jid.argc > 2) {
1821 ast_log(LOG_WARNING, "Wrong JID %s, exiting\n", args.jid);
1822 return -1;
1823 }
1824
1825 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1826 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
1827 return -1;
1828 }
1829
1830 snprintf(buf, buflen, "%d", get_buddy_status(clientcfg, jid.screenname, jid.resource));
1831
1832 return 0;
1833}
#define LOG_ERROR
static int get_buddy_status(struct ast_xmpp_client_config *clientcfg, char *screenname, char *resource)
Definition: res_xmpp.c:1759

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 4832 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 1072 of file res_xmpp.c.

1073{
1074 int res = 0;
1075 iks *invite, *body = NULL, *namespace = NULL;
1076
1077 if (!(invite = iks_new("message")) || !(body = iks_new("body")) || !(namespace = iks_new("x"))) {
1078 res = -1;
1079 goto done;
1080 }
1081
1082 iks_insert_attrib(invite, "to", user);
1083 ast_xmpp_client_lock(client);
1084 iks_insert_attrib(invite, "id", client->mid);
1085 ast_xmpp_increment_mid(client->mid);
1086 ast_xmpp_client_unlock(client);
1087 iks_insert_cdata(body, message, 0);
1088 iks_insert_node(invite, body);
1089 iks_insert_attrib(namespace, "xmlns", "jabber:x:conference");
1090 iks_insert_attrib(namespace, "jid", room);
1091 iks_insert_node(invite, namespace);
1092
1093 res = ast_xmpp_client_send(client, invite);
1094
1095done:
1096 iks_delete(namespace);
1097 iks_delete(body);
1098 iks_delete(invite);
1099
1100 return res;
1101}
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:2663
void ast_xmpp_client_unlock(struct ast_xmpp_client *client)
Unlock an XMPP client connection.
Definition: res_xmpp.c:1033
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1154
void ast_xmpp_client_lock(struct ast_xmpp_client *client)
Lock an XMPP client connection.
Definition: res_xmpp.c:1028
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 1139 of file res_xmpp.c.

1140{
1141 return xmpp_client_set_group_presence(client, room, IKS_SHOW_AVAILABLE, nickname);
1142}
static int xmpp_client_set_group_presence(struct ast_xmpp_client *client, const char *room, int level, const char *nick)
Definition: res_xmpp.c:1103

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 1149 of file res_xmpp.c.

1150{
1151 return xmpp_client_set_group_presence(client, room, IKS_SHOW_UNAVAILABLE, nickname);
1152}

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 1144 of file res_xmpp.c.

1145{
1146 return xmpp_client_send_message(client, 1, nickname, address, message);
1147}
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:1039

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 806 of file res_xmpp.c.

807{
808 struct ast_xmpp_client_config *cfg;
809
810 if (!(cfg = ao2_alloc(sizeof(*cfg), ast_xmpp_client_config_destructor))) {
811 return NULL;
812 }
813
814 if (ast_string_field_init(cfg, 512)) {
815 ao2_ref(cfg, -1);
816 return NULL;
817 }
818
819 if (!(cfg->client = xmpp_client_find_or_create(cat))) {
820 ao2_ref(cfg, -1);
821 return NULL;
822 }
823
826 if (!cfg->buddies) {
827 ao2_ref(cfg, -1);
828 return NULL;
829 }
830
831 ast_string_field_set(cfg, name, cat);
832
833 return cfg;
834}
@ 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:716
#define BUDDY_BUCKETS
Number of buckets for buddies (per client)
Definition: res_xmpp.c:558
static void * xmpp_client_find_or_create(const char *category)
Look up existing client or create a new one.
Definition: res_xmpp.c:792
static void ast_xmpp_client_config_destructor(void *obj)
Destructor function for configuration.
Definition: res_xmpp.c:658
static int xmpp_buddy_hash(const void *obj, const int flags)
Hashing function for XMPP buddy.
Definition: res_xmpp.c:707
#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:599
struct ast_xmpp_client * client
Definition: res_xmpp.c:598

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 658 of file res_xmpp.c.

659{
660 struct ast_xmpp_client_config *cfg = obj;
662 ao2_cleanup(cfg->client);
663 ao2_cleanup(cfg->buddies);
664}
#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 3654 of file res_xmpp.c.

3655{
3656 if ((client->thread != AST_PTHREADT_NULL) && !pthread_equal(pthread_self(), client->thread)) {
3658 pthread_cancel(client->thread);
3659 pthread_join(client->thread, NULL);
3660 client->thread = AST_PTHREADT_NULL;
3661 }
3662
3663 if (client->mwi_sub) {
3664 client->mwi_sub = stasis_unsubscribe_and_join(client->mwi_sub);
3665 xmpp_pubsub_unsubscribe(client, "message_waiting");
3666 }
3667
3668 if (client->device_state_sub) {
3670 xmpp_pubsub_unsubscribe(client, "device_state");
3671 }
3672
3673#ifdef HAVE_OPENSSL
3674 if (client->stream_flags & SECURE) {
3675 SSL_shutdown(client->ssl_session);
3676 SSL_CTX_free(client->ssl_context);
3677 SSL_free(client->ssl_session);
3678 }
3679
3680 client->stream_flags = 0;
3681#endif
3682
3683 if (client->parser) {
3684 iks_disconnect(client->parser);
3685 }
3686
3688
3689 return 0;
3690}
#define AST_PTHREADT_NULL
Definition: lock.h:73
static void xmpp_pubsub_unsubscribe(struct ast_xmpp_client *client, const char *node)
Unsubscribe from a PubSub node.
Definition: res_xmpp.c:1514
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:725
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1161
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 1010 of file res_xmpp.c.

1011{
1013 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1014
1015 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
1016 return NULL;
1017 }
1018
1019 ao2_ref(clientcfg->client, +1);
1020 return clientcfg->client;
1021}

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 1028 of file res_xmpp.c.

1029{
1030 ao2_lock(client);
1031}
#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 2663 of file res_xmpp.c.

2664{
2665 return xmpp_client_send_raw_message(client, iks_string(iks_stack(stanza), stanza));
2666}
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:2618

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 1067 of file res_xmpp.c.

1068{
1069 return xmpp_client_send_message(client, 0, NULL, user, message);
1070}

References NULL, and xmpp_client_send_message().

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

◆ ast_xmpp_client_unlock()

void ast_xmpp_client_unlock ( struct ast_xmpp_client client)

Unlock an XMPP client connection.

Parameters
clientPointer to the client

Definition at line 1033 of file res_xmpp.c.

1034{
1035 ao2_unlock(client);
1036}
#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 1023 of file res_xmpp.c.

1024{
1025 ao2_ref(client, -1);
1026}

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 1154 of file res_xmpp.c.

1155{
1156 int i = 0;
1157
1158 for (i = strlen(mid) - 1; i >= 0; i--) {
1159 if (mid[i] != 'z') {
1160 mid[i] = mid[i] + 1;
1161 i = 0;
1162 } else {
1163 mid[i] = 'a';
1164 }
1165 }
1166}

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 1700 of file res_xmpp.c.

1701{
1702 struct stasis_message *msg = obj;
1703 struct ast_xmpp_client *client = arg;
1704 xmpp_pubsub_devstate_cb(client, client->device_state_sub, msg);
1705 return 0;
1706}
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:1491
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 4654 of file res_xmpp.c.

4655{
4656 struct ast_xmpp_client_config *cfg = obj;
4657
4658 if (!strcasecmp(var->name, "debug")) {
4659 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_DEBUG);
4660 } else if (!strcasecmp(var->name, "type")) {
4661 ast_set2_flag(&cfg->flags, !strcasecmp(var->value, "component") ? 1 : 0, XMPP_COMPONENT);
4662 } else if (!strcasecmp(var->name, "distribute_events")) {
4664 } else if (!strcasecmp(var->name, "usetls")) {
4665 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_USETLS);
4666 } else if (!strcasecmp(var->name, "usesasl")) {
4667 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_USESASL);
4668 } else if (!strcasecmp(var->name, "forceoldssl")) {
4669 ast_set2_flag(&cfg->flags, ast_true(var->value), XMPP_FORCESSL);
4670 } else if (!strcasecmp(var->name, "keepalive")) {
4672 } else if (!strcasecmp(var->name, "autoprune")) {
4675 } else if (!strcasecmp(var->name, "autoregister")) {
4678 } else if (!strcasecmp(var->name, "auth_policy")) {
4679 ast_set2_flag(&cfg->flags, !strcasecmp(var->value, "accept") ? 1 : 0, XMPP_AUTOACCEPT);
4681 } else if (!strcasecmp(var->name, "sendtodialplan")) {
4683 } else {
4684 return -1;
4685 }
4686
4687 return 0;
4688}
#define var
Definition: ast_expr2f.c:605
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
struct ast_flags flags
Definition: res_xmpp.c:595
struct ast_flags mod_flags
Definition: res_xmpp.c:596
#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 4719 of file res_xmpp.c.

4720{
4721 struct ast_xmpp_client_config *cfg = obj;
4722 struct ast_xmpp_buddy *buddy;
4723
4724 if ((buddy = ao2_find(cfg->buddies, var->value, OBJ_KEY))) {
4725 ao2_ref(buddy, -1);
4726 return -1;
4727 }
4728
4729 if (!(buddy = xmpp_client_create_buddy(cfg->buddies, var->value))) {
4730 return -1;
4731 }
4732
4733 ao2_ref(buddy, -1);
4734
4735 return 0;
4736}
#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:2292
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 4690 of file res_xmpp.c.

4691{
4692 struct ast_xmpp_client_config *cfg = obj;
4693
4694 if (!strcasecmp(var->value, "unavailable")) {
4695 cfg->status = IKS_SHOW_UNAVAILABLE;
4696 } else if (!strcasecmp(var->value, "available") || !strcasecmp(var->value, "online")) {
4697 cfg->status = IKS_SHOW_AVAILABLE;
4698 } else if (!strcasecmp(var->value, "chat") || !strcasecmp(var->value, "chatty")) {
4699 cfg->status = IKS_SHOW_CHAT;
4700 } else if (!strcasecmp(var->value, "away")) {
4701 cfg->status = IKS_SHOW_AWAY;
4702 } else if (!strcasecmp(var->value, "xa") || !strcasecmp(var->value, "xaway")) {
4703 cfg->status = IKS_SHOW_XA;
4704 } else if (!strcasecmp(var->value, "dnd")) {
4705 cfg->status = IKS_SHOW_DND;
4706 } else if (!strcasecmp(var->value, "invisible")) {
4707#ifdef IKS_SHOW_INVISIBLE
4708 cfg->status = IKS_SHOW_INVISIBLE;
4709#else
4710 cfg->status = IKS_SHOW_DND;
4711#endif
4712 } else {
4713 return -1;
4714 }
4715
4716 return 0;
4717}
enum ikshowtype status
Definition: res_xmpp.c:597

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 2221 of file res_xmpp.c.

2222{
2224 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2225 int deleted = 0, isold = 0;
2226 struct ast_xmpp_message *message = NULL;
2227
2228 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
2229 return 0;
2230 }
2231
2232 AST_LIST_LOCK(&client->messages);
2234 if (isold) {
2235 if (!from || !strncasecmp(from, message->from, strlen(from))) {
2238 deleted++;
2239 }
2240 } else if (ast_tvdiff_sec(ast_tvnow(), message->arrived) >= clientcfg->message_timeout) {
2241 isold = 1;
2242 if (!from || !strncasecmp(from, message->from, strlen(from))) {
2245 deleted++;
2246 }
2247 }
2248 }
2250 AST_LIST_UNLOCK(&client->messages);
2251
2252 return deleted;
2253}
struct ast_xmpp_client::@292 messages
const ast_string_field name
Definition: xmpp.h:123
char * from
Definition: xmpp.h:102
struct ast_xmpp_message::@291 list

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

Referenced by xmpp_pak_message().

◆ fetch_access_token()

static int fetch_access_token ( struct ast_xmpp_client_config cfg)
static

Definition at line 3953 of file res_xmpp.c.

3954{
3955 RAII_VAR(char *, cmd, NULL, ast_free);
3956 char cBuf[1024] = "";
3957 const char *url = "https://www.googleapis.com/oauth2/v3/token";
3958 struct ast_json_error error;
3959 RAII_VAR(struct ast_json *, jobj, NULL, ast_json_unref);
3960
3961 if (ast_asprintf(&cmd,
3962 "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
3963 url, cfg->oauth_clientid, cfg->oauth_secret, cfg->refresh_token) < 0) {
3964 return -1;
3965 }
3966
3967 ast_debug(2, "Performing OAuth 2.0 authentication for client '%s' using command: %s\n",
3968 cfg->name, cmd);
3969
3970 if (ast_func_read(NULL, cmd, cBuf, sizeof(cBuf) - 1)) {
3971 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",
3972 cfg->name);
3973 return -1;
3974 }
3975
3976 ast_debug(2, "OAuth 2.0 authentication for client '%s' returned: %s\n", cfg->name, cBuf);
3977
3978 jobj = ast_json_load_string(cBuf, &error);
3979 if (jobj) {
3980 const char *token = ast_json_string_get(ast_json_object_get(jobj, "access_token"));
3981 if (token) {
3982 ast_string_field_set(cfg, password, token);
3983 return 0;
3984 }
3985 }
3986
3987 ast_log(LOG_ERROR, "An error occurred while performing OAuth 2.0 authentication for client '%s': %s\n", cfg->name, cBuf);
3988
3989 return -1;
3990}
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_load_string(const char *input, struct ast_json_error *error)
Parse null terminated string into a JSON object or array.
Definition: json.c:567
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
static char url[512]
JSON parsing error information.
Definition: json.h:887
Abstract JSON element (object, array, string, int, ...).
const ast_string_field oauth_clientid
Definition: res_xmpp.c:591
const ast_string_field oauth_secret
Definition: res_xmpp.c:591
const ast_string_field name
Definition: res_xmpp.c:591
const ast_string_field refresh_token
Definition: res_xmpp.c:591
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 1759 of file res_xmpp.c.

1760{
1761 int status = BUDDY_OFFLINE;
1762 struct ast_xmpp_resource *res;
1763 struct ast_xmpp_buddy *buddy = ao2_find(clientcfg->client->buddies, screenname, OBJ_KEY);
1764
1765 if (!buddy) {
1766 return BUDDY_NOT_IN_ROSTER;
1767 }
1768
1769 res = ao2_callback(
1770 buddy->resources,
1771 0,
1773 resource);
1774
1775 if (res) {
1776 status = res->status;
1777 }
1778
1779 ao2_cleanup(res);
1780 ao2_cleanup(buddy);
1781
1782 return status;
1783}
jack_status_t status
Definition: app_jack.c:149
#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:1751
static int xmpp_resource_cmp(void *obj, void *arg, int flags)
Comparator function for XMPP resource.
Definition: res_xmpp.c:982
#define BUDDY_NOT_IN_ROSTER
Definition: res_xmpp.c:1757
#define BUDDY_OFFLINE
Definition: res_xmpp.c:1756
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 4631 of file res_xmpp.c.

4632{
4633 struct ast_xmpp_global_config *global = obj;
4634
4635 if (!strcasecmp(var->name, "debug")) {
4636 debug = ast_true(var->value);
4637 } else if (!strcasecmp(var->name, "autoprune")) {
4638 ast_set2_flag(&global->general, ast_true(var->value), XMPP_AUTOPRUNE);
4639 } else if (!strcasecmp(var->name, "autoregister")) {
4640 ast_set2_flag(&global->general, ast_true(var->value), XMPP_AUTOREGISTER);
4641 } else if (!strcasecmp(var->name, "auth_policy")) {
4642 ast_set2_flag(&global->general, !strcasecmp(var->value, "accept") ? 1 : 0, XMPP_AUTOACCEPT);
4643 } else if (!strcasecmp(var->name, "collection_nodes")) {
4644 ast_set2_flag(&global->pubsub, ast_true(var->value), XMPP_XEP0248);
4645 } else if (!strcasecmp(var->name, "pubsub_autocreate")) {
4647 } else {
4648 return -1;
4649 }
4650
4651 return 0;
4652}
static int debug
Global debug status.
Definition: res_xmpp.c:570
XMPP Global Configuration.
Definition: res_xmpp.c:573
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 4748 of file res_xmpp.c.

4749{
4750 if (aco_info_init(&cfg_info)) {
4752 }
4753
4756 aco_option_register_custom(&cfg_info, "autoregister", ACO_EXACT, global_options, "yes", global_bitfield_handler, 0);
4757 aco_option_register_custom(&cfg_info, "collection_nodes", ACO_EXACT, global_options, "no", global_bitfield_handler, 0);
4758 aco_option_register_custom(&cfg_info, "pubsub_autocreate", ACO_EXACT, global_options, "no", global_bitfield_handler, 0);
4759 aco_option_register_custom(&cfg_info, "auth_policy", ACO_EXACT, global_options, "accept", global_bitfield_handler, 0);
4760
4763 aco_option_register(&cfg_info, "refresh_token", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, refresh_token));
4764 aco_option_register(&cfg_info, "oauth_clientid", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, oauth_clientid));
4765 aco_option_register(&cfg_info, "oauth_secret", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, oauth_secret));
4767 aco_option_register(&cfg_info, "statusmessage", ACO_EXACT, client_options, "Online and Available", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, statusmsg));
4768 aco_option_register(&cfg_info, "pubsub_node", ACO_EXACT, client_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, pubsubnode));
4771 aco_option_register(&cfg_info, "port", ACO_EXACT, client_options, "5222", OPT_UINT_T, 0, FLDSET(struct ast_xmpp_client_config, port));
4772 aco_option_register(&cfg_info, "timeout", ACO_EXACT, client_options, "5", OPT_UINT_T, 0, FLDSET(struct ast_xmpp_client_config, message_timeout));
4773
4774 /* Global options that can be overridden per client must not specify a default */
4778
4781 aco_option_register_custom(&cfg_info, "distribute_events", ACO_EXACT, client_options, "no", client_bitfield_handler, 0);
4784 aco_option_register_custom(&cfg_info, "forceoldssl", ACO_EXACT, client_options, "no", client_bitfield_handler, 0);
4786 aco_option_register_custom(&cfg_info, "sendtodialplan", ACO_EXACT, client_options, "no", client_bitfield_handler, 0);
4787 aco_option_register_custom(&cfg_info, "status", ACO_EXACT, client_options, "available", client_status_handler, 0);
4789
4790 if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
4791 aco_info_destroy(&cfg_info);
4793 }
4794
4796
4801
4806
4809
4811 ast_log(LOG_WARNING, "Entity ID is not set. The distributing device state or MWI will not work.\n");
4812 }
4813
4815}
static int priority
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
@ ACO_EXACT
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_mutex_init(pmutex)
Definition: lock.h:193
#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:192
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:640
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
struct aco_type * global_options[]
Definition: res_xmpp.c:937
static int xmpp_send_exec(struct ast_channel *chan, const char *data)
Definition: res_xmpp.c:1967
static const char * app_ajijoin
Definition: res_xmpp.c:648
static int global_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4631
static struct ast_custom_function jabberstatus_function
Definition: res_xmpp.c:1835
static const char * app_ajisendgroup
Definition: res_xmpp.c:646
struct aco_type * client_options[]
Definition: res_xmpp.c:950
static int client_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4654
static int manager_jabber_send(struct mansession *s, const struct message *m)
Definition: res_xmpp.c:4053
static int xmpp_join_exec(struct ast_channel *chan, const char *data)
Application to join a chat room.
Definition: res_xmpp.c:1847
static const char * app_ajileave
Definition: res_xmpp.c:649
static const char * app_ajisend
Definition: res_xmpp.c:645
static struct ast_cli_entry xmpp_cli[]
Definition: res_xmpp.c:4599
static int client_buddy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4719
static struct ast_custom_function jabberreceive_function
Definition: res_xmpp.c:2208
static const struct ast_msg_tech msg_tech
Definition: res_xmpp.c:2286
static int client_status_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: res_xmpp.c:4690
static int xmpp_leave_exec(struct ast_channel *chan, const char *data)
Application to leave a chat room.
Definition: res_xmpp.c:1906
static int xmpp_sendgroup_exec(struct ast_channel *chan, const char *data)
Application to send a message to a groupchat.
Definition: res_xmpp.c:2008
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
Definition: utils.c:3099
#define ARRAY_LEN(a)
Definition: utils.h:666
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:94

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

◆ manager_jabber_send()

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

Definition at line 4053 of file res_xmpp.c.

4054{
4056 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4057 const char *id = astman_get_header(m, "ActionID");
4058 const char *jabber = astman_get_header(m, "Jabber");
4059 const char *screenname = astman_get_header(m, "ScreenName");
4060 const char *message = astman_get_header(m, "Message");
4061
4062 if (ast_strlen_zero(jabber)) {
4063 astman_send_error(s, m, "No transport specified");
4064 return 0;
4065 }
4066 if (ast_strlen_zero(screenname)) {
4067 astman_send_error(s, m, "No ScreenName specified");
4068 return 0;
4069 }
4070 if (ast_strlen_zero(message)) {
4071 astman_send_error(s, m, "No Message specified");
4072 return 0;
4073 }
4074
4075 astman_send_ack(s, m, "Attempting to send Jabber Message");
4076
4077 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, jabber))) {
4078 astman_send_error(s, m, "Could not find Sender");
4079 return 0;
4080 }
4081
4082 if (strchr(screenname, '@') && !ast_xmpp_client_send_message(clientcfg->client, screenname, message)) {
4083 astman_append(s, "Response: Success\r\n");
4084 } else {
4085 astman_append(s, "Response: Error\r\n");
4086 }
4087
4088 if (!ast_strlen_zero(id)) {
4089 astman_append(s, "ActionID: %s\r\n", id);
4090 }
4091
4092 astman_append(s, "\r\n");
4093
4094 return 0;
4095}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
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:1067

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 4817 of file res_xmpp.c.

4818{
4819 if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
4821 }
4822
4823 return 0;
4824}

References aco_process_config(), ACO_PROCESS_ERROR, and AST_MODULE_LOAD_DECLINE.

◆ sleep_with_backoff()

static void sleep_with_backoff ( unsigned int *  sleep_time)
static

Definition at line 3845 of file res_xmpp.c.

3846{
3847 /* We're OK with our thread dying here */
3848 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
3849
3850 sleep(*sleep_time);
3851 *sleep_time = MIN(60, *sleep_time * 2);
3852
3853 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
3854}
#define MIN(a, b)
Definition: utils.h:231

References MIN, and NULL.

Referenced by xmpp_client_thread().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4610 of file res_xmpp.c.

4611{
4619 ast_manager_unregister("JabberSend");
4622 aco_info_destroy(&cfg_info);
4624
4627
4628 return 0;
4629}
#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:7697
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define ast_mutex_destroy(a)
Definition: lock.h:195
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:647

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 3584 of file res_xmpp.c.

3585{
3587 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3588 struct ast_xmpp_client *client = data;
3589 ikspak *pak;
3590 int i;
3591
3592 if (!node) {
3593 ast_log(LOG_ERROR, "xmpp_action_hook was called without a packet\n");
3594 return IKS_HOOK;
3595 }
3596
3597 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
3598 return IKS_HOOK;
3599 }
3600
3601 /* If the client is disconnecting ignore everything */
3602 if (client->state == XMPP_STATE_DISCONNECTING) {
3603 return IKS_HOOK;
3604 }
3605
3606 pak = iks_packet(node);
3607
3608 /* work around iksemel's impossibility to recognize node names
3609 * containing a colon. Set the namespace of the corresponding
3610 * node accordingly. */
3611 if (iks_has_children(node) && strchr(iks_name(iks_child(node)), ':')) {
3612 char *node_ns = NULL;
3613 char attr[XMPP_MAX_ATTRLEN];
3614 char *node_name = iks_name(iks_child(node));
3615 char *aux = strchr(node_name, ':') + 1;
3616 snprintf(attr, strlen("xmlns:") + (strlen(node_name) - strlen(aux)), "xmlns:%s", node_name);
3617 node_ns = iks_find_attrib(iks_child(node), attr);
3618 if (node_ns) {
3619 pak->ns = node_ns;
3620 pak->query = iks_child(node);
3621 }
3622 }
3623
3624 /* Process through any state handlers */
3625 for (i = 0; i < ARRAY_LEN(xmpp_state_handlers); i++) {
3626 if ((xmpp_state_handlers[i].state == client->state) && (xmpp_state_handlers[i].component == (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) ? 1 : 0))) {
3627 if (xmpp_state_handlers[i].handler(client, clientcfg, type, node)) {
3628 /* If the handler wants us to stop now, do so */
3629 return IKS_HOOK;
3630 }
3631 break;
3632 }
3633 }
3634
3635 /* Process through any PAK handlers */
3636 for (i = 0; i < ARRAY_LEN(xmpp_pak_handlers); i++) {
3637 if (xmpp_pak_handlers[i].type == pak->type) {
3638 if (xmpp_pak_handlers[i].handler(client, clientcfg, node, pak)) {
3639 /* If the handler wants us to stop now, do so */
3640 return IKS_HOOK;
3641 }
3642 break;
3643 }
3644 }
3645
3646 /* Send the packet through the filter in case any filters want to process it */
3647 iks_filter_packet(client->filter, pak);
3648
3649 iks_delete(node);
3650
3651 return IKS_OK;
3652}
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 716 of file res_xmpp.c.

717{
718 struct ast_xmpp_buddy *buddy1 = obj, *buddy2 = arg;
719 const char *id = arg;
720
721 return !strcmp(buddy1->id, flags & OBJ_KEY ? id : buddy2->id) ? CMP_MATCH | CMP_STOP : 0;
722}
@ 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 991 of file res_xmpp.c.

992{
993 struct ast_xmpp_buddy *buddy = obj;
994
995 if (buddy->resources) {
996 ao2_ref(buddy->resources, -1);
997 }
998}

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 707 of file res_xmpp.c.

708{
709 const struct ast_xmpp_buddy *buddy = obj;
710 const char *id = obj;
711
712 return ast_str_hash(flags & OBJ_KEY ? id : buddy->id);
713}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259

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

Referenced by ast_xmpp_client_config_alloc(), and xmpp_client_alloc().

◆ xmpp_cli_create_collection()

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

Method to expose PubSub collection node creation via CLI.

Returns
char *

Definition at line 4347 of file res_xmpp.c.

4348{
4350 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4351 const char *name, *collection_name;
4352
4353 switch (cmd) {
4354 case CLI_INIT:
4355 e->command = "xmpp create collection";
4356 e->usage =
4357 "Usage: xmpp create collection <connection> <collection>\n"
4358 " Creates a PubSub collection node using the account\n"
4359 " as configured in xmpp.conf.\n";
4360 return NULL;
4361 case CLI_GENERATE:
4362 return NULL;
4363 }
4364
4365 if (a->argc != 5) {
4366 return CLI_SHOWUSAGE;
4367 }
4368 name = a->argv[3];
4369 collection_name = a->argv[4];
4370
4371 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4372 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4373 return CLI_FAILURE;
4374 }
4375
4376 ast_cli(a->fd, "Creating test PubSub node collection.\n");
4377
4378 xmpp_pubsub_create_collection(clientcfg->client, collection_name);
4379
4380 return CLI_SUCCESS;
4381}
#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:1373
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 4387 of file res_xmpp.c.

4388{
4390 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4391 const char *name, *collection_name, *leaf_name;
4392
4393 switch (cmd) {
4394 case CLI_INIT:
4395 e->command = "xmpp create leaf";
4396 e->usage =
4397 "Usage: xmpp create leaf <connection> <collection> <leaf>\n"
4398 " Creates a PubSub leaf node using the account\n"
4399 " as configured in xmpp.conf.\n";
4400 return NULL;
4401 case CLI_GENERATE:
4402 return NULL;
4403 }
4404
4405 if (a->argc != 6) {
4406 return CLI_SHOWUSAGE;
4407 }
4408 name = a->argv[3];
4409 collection_name = a->argv[4];
4410 leaf_name = a->argv[5];
4411
4412 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4413 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4414 return CLI_FAILURE;
4415 }
4416
4417 ast_cli(a->fd, "Creating test PubSub node collection.\n");
4418
4419 xmpp_pubsub_create_leaf(clientcfg->client, collection_name, leaf_name);
4420
4421 return CLI_SUCCESS;
4422}
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:1385

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 4309 of file res_xmpp.c.

4311{
4313 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4314 const char *name;
4315
4316 switch (cmd) {
4317 case CLI_INIT:
4318 e->command = "xmpp delete node";
4319 e->usage =
4320 "Usage: xmpp delete node <connection> <node>\n"
4321 " Deletes a node on PubSub server\n"
4322 " as configured in xmpp.conf.\n";
4323 return NULL;
4324 case CLI_GENERATE:
4325 return NULL;
4326 }
4327
4328 if (a->argc != 5) {
4329 return CLI_SHOWUSAGE;
4330 }
4331 name = a->argv[3];
4332
4333 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4334 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4335 return CLI_FAILURE;
4336 }
4337
4338 xmpp_pubsub_delete_node(clientcfg->client, a->argv[4]);
4339
4340 return CLI_SUCCESS;
4341}
static void xmpp_pubsub_delete_node(struct ast_xmpp_client *client, const char *node_name)
Delete a PubSub node.
Definition: res_xmpp.c:1351

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 4178 of file res_xmpp.c.

4180{
4182 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4183 const char *name = NULL, *collection = NULL;
4184
4185 switch (cmd) {
4186 case CLI_INIT:
4187 e->command = "xmpp list nodes";
4188 e->usage =
4189 "Usage: xmpp list nodes <connection> [collection]\n"
4190 " Lists the user's nodes on the respective connection\n"
4191 " ([connection] as configured in xmpp.conf.)\n";
4192 return NULL;
4193 case CLI_GENERATE:
4194 return NULL;
4195 }
4196
4197 if (a->argc > 5 || a->argc < 4) {
4198 return CLI_SHOWUSAGE;
4199 } else if (a->argc == 4 || a->argc == 5) {
4200 name = a->argv[3];
4201 }
4202
4203 if (a->argc == 5) {
4204 collection = a->argv[4];
4205 }
4206
4207 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4208 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4209 return CLI_FAILURE;
4210 }
4211
4212 ast_cli(a->fd, "Listing pubsub nodes.\n");
4213
4214 xmpp_pubsub_request_nodes(clientcfg->client, collection);
4215
4216 return CLI_SUCCESS;
4217}
static void xmpp_pubsub_request_nodes(struct ast_xmpp_client *client, const char *collection)
Request item list from pubsub.
Definition: res_xmpp.c:4154

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 4264 of file res_xmpp.c.

4266{
4268 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
4269 const char *name;
4270
4271 switch (cmd) {
4272 case CLI_INIT:
4273 e->command = "xmpp purge nodes";
4274 e->usage =
4275 "Usage: xmpp purge nodes <connection> <node>\n"
4276 " Purges nodes on PubSub server\n"
4277 " as configured in xmpp.conf.\n";
4278 return NULL;
4279 case CLI_GENERATE:
4280 return NULL;
4281 }
4282
4283 if (a->argc != 5) {
4284 return CLI_SHOWUSAGE;
4285 }
4286 name = a->argv[3];
4287
4288 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, name))) {
4289 ast_cli(a->fd, "Unable to find client '%s'!\n", name);
4290 return CLI_FAILURE;
4291 }
4292
4293 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
4294 xmpp_pubsub_purge_nodes(clientcfg->client, a->argv[4]);
4295 } else {
4296 xmpp_pubsub_delete_node(clientcfg->client, a->argv[4]);
4297 }
4298
4299 return CLI_SUCCESS;
4300}
static void xmpp_pubsub_purge_nodes(struct ast_xmpp_client *client, const char *collection_name)
Definition: res_xmpp.c:4246

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 739 of file res_xmpp.c.

740{
741 struct ast_xmpp_client *client;
742
743 if (!(client = ao2_alloc(sizeof(*client), xmpp_client_destructor))) {
744 return NULL;
745 }
746
748 client->thread = AST_PTHREADT_NULL;
749
750 client->endpoint = ast_endpoint_create("XMPP", name);
751 if (!client->endpoint) {
752 ao2_ref(client, -1);
753 return NULL;
754 }
755
758 if (!client->buddies) {
759 ast_log(LOG_ERROR, "Could not initialize buddy container for '%s'\n", name);
760 ao2_ref(client, -1);
761 return NULL;
762 }
763
764 if (ast_string_field_init(client, 512)) {
765 ast_log(LOG_ERROR, "Could not initialize stringfields for '%s'\n", name);
766 ao2_ref(client, -1);
767 return NULL;
768 }
769
770 if (!(client->stack = iks_stack_new(8192, 8192))) {
771 ast_log(LOG_ERROR, "Could not create an Iksemel stack for '%s'\n", name);
772 ao2_ref(client, -1);
773 return NULL;
774 }
775
777
778 client->timeout = 50;
780 ast_copy_string(client->mid, "aaaaa", sizeof(client->mid));
781
782 return client;
783}
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:680
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 2886 of file res_xmpp.c.

2887{
2889}
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:2783
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:2821

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 2783 of file res_xmpp.c.

2784{
2785 iks *iq = NULL, *query = NULL;
2786 char buf[41], sidpass[100];
2787
2788 if (!(iq = iks_new("iq")) || !(query = iks_insert(iq, "query"))) {
2789 ast_log(LOG_ERROR, "Stanzas could not be allocated for authentication on client '%s'\n", client->name);
2790 iks_delete(iq);
2791 return -1;
2792 }
2793
2794 iks_insert_attrib(iq, "type", "set");
2795 iks_insert_cdata(iks_insert(query, "username"), client->jid->user, 0);
2796 iks_insert_cdata(iks_insert(query, "resource"), client->jid->resource, 0);
2797
2798 iks_insert_attrib(query, "xmlns", "jabber:iq:auth");
2799 snprintf(sidpass, sizeof(sidpass), "%s%s", iks_find_attrib(node, "id"), cfg->password);
2800 ast_sha1_hash(buf, sidpass);
2801 iks_insert_cdata(iks_insert(query, "digest"), buf, 0);
2802
2803 ast_xmpp_client_lock(client);
2804 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);
2805 iks_insert_attrib(iq, "id", client->mid);
2806 ast_xmpp_increment_mid(client->mid);
2807 ast_xmpp_client_unlock(client);
2808
2809 iks_insert_attrib(iq, "to", client->jid->server);
2810
2811 ast_xmpp_client_send(client, iq);
2812
2813 iks_delete(iq);
2814
2816
2817 return 0;
2818}
static int xmpp_connect_hook(void *data, ikspak *pak)
Hook function called when client finishes authenticating with the server.
Definition: res_xmpp.c:2562
const ast_string_field password
Definition: res_xmpp.c:591
iksid * jid
Definition: xmpp.h:126
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: utils.c:266
@ XMPP_STATE_AUTHENTICATING
Definition: xmpp.h:78

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

Referenced by xmpp_client_authenticate().

◆ xmpp_client_authenticate_sasl()

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

Internal function called when we need to authenticate using SASL.

Definition at line 2821 of file res_xmpp.c.

2822{
2823 int features, len = strlen(client->jid->user) + strlen(cfg->password) + 3;
2824 iks *auth;
2825 char combined[len];
2826 char base64[(len + 2) * 4 / 3];
2827
2828 if (strcmp(iks_name(node), "stream:features")) {
2829 /* Ignore anything beside stream features */
2830 return 0;
2831 }
2832
2833 features = iks_stream_features(node);
2834
2835 if ((features & IKS_STREAM_SASL_MD5) && !xmpp_is_secure(client)) {
2836 if (iks_start_sasl(client->parser, IKS_SASL_DIGEST_MD5, (char*)client->jid->user, (char*)cfg->password) != IKS_OK) {
2837 ast_log(LOG_ERROR, "Tried to authenticate client '%s' using SASL DIGEST-MD5 but could not\n", client->name);
2838 return -1;
2839 }
2840
2842 return 0;
2843 }
2844
2845 /* Our only other available option is plain so if they don't support it, bail out now */
2846 if (!(features & IKS_STREAM_SASL_PLAIN)) {
2847 ast_log(LOG_ERROR, "Tried to authenticate client '%s' using SASL PLAIN but server does not support it\n", client->name);
2848 return -1;
2849 }
2850
2851 if (!(auth = iks_new("auth"))) {
2852 ast_log(LOG_ERROR, "Could not allocate memory for SASL PLAIN authentication for client '%s'\n", client->name);
2853 return -1;
2854 }
2855
2856 iks_insert_attrib(auth, "xmlns", IKS_NS_XMPP_SASL);
2857 if (!ast_strlen_zero(cfg->refresh_token)) {
2858 iks_insert_attrib(auth, "mechanism", "X-OAUTH2");
2859 iks_insert_attrib(auth, "auth:service", "oauth2");
2860 iks_insert_attrib(auth, "xmlns:auth", "http://www.google.com/talk/protocol/auth");
2861 } else {
2862 iks_insert_attrib(auth, "mechanism", "PLAIN");
2863 }
2864
2865 if (strchr(client->jid->user, '/')) {
2866 char *user = ast_strdupa(client->jid->user);
2867
2868 snprintf(combined, sizeof(combined), "%c%s%c%s", 0, strsep(&user, "/"), 0, cfg->password);
2869 } else {
2870 snprintf(combined, sizeof(combined), "%c%s%c%s", 0, client->jid->user, 0, cfg->password);
2871 }
2872
2873 ast_base64encode(base64, (const unsigned char *) combined, len - 1, (len + 2) * 4 / 3);
2874 iks_insert_cdata(auth, base64, 0);
2875
2876 ast_xmpp_client_send(client, auth);
2877
2878 iks_delete(auth);
2879
2881
2882 return 0;
2883}
char * strsep(char **str, const char *delims)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:1001
static char base64[64]
Definition: utils.c:80
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:406

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

Referenced by xmpp_client_authenticate().

◆ xmpp_client_authenticating()

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

Internal function called when we are authenticating.

Definition at line 2892 of file res_xmpp.c.

2893{
2894 int features;
2895
2896 if (!strcmp(iks_name(node), "success")) {
2897 /* Authentication was a success, yay! */
2898 xmpp_send_stream_header(client, cfg, client->jid->server);
2899
2900 return 0;
2901 } else if (!strcmp(iks_name(node), "failure")) {
2902 /* Authentication was a bust, disconnect and reconnect later */
2903 return -1;
2904 } else if (strcmp(iks_name(node), "stream:features")) {
2905 /* Ignore any other responses */
2906 return 0;
2907 }
2908
2909 features = iks_stream_features(node);
2910
2911 if (features & IKS_STREAM_BIND) {
2912 iks *auth;
2913
2914 if (!(auth = iks_make_resource_bind(client->jid))) {
2915 ast_log(LOG_ERROR, "Failed to allocate memory for stream bind on client '%s'\n", client->name);
2916 return -1;
2917 }
2918
2919 ast_xmpp_client_lock(client);
2920 iks_insert_attrib(auth, "id", client->mid);
2921 ast_xmpp_increment_mid(client->mid);
2922 ast_xmpp_client_unlock(client);
2923 ast_xmpp_client_send(client, auth);
2924
2925 iks_delete(auth);
2926
2927 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);
2928 }
2929
2930 if (features & IKS_STREAM_SESSION) {
2931 iks *auth;
2932
2933 if (!(auth = iks_make_session())) {
2934 ast_log(LOG_ERROR, "Failed to allocate memory for stream session on client '%s'\n", client->name);
2935 return -1;
2936 }
2937
2938 iks_insert_attrib(auth, "id", "auth");
2939 ast_xmpp_client_lock(client);
2940 ast_xmpp_increment_mid(client->mid);
2941 ast_xmpp_client_unlock(client);
2942 ast_xmpp_client_send(client, auth);
2943
2944 iks_delete(auth);
2945
2946 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);
2947 }
2948
2949 return 0;
2950}
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:2651

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 725 of file res_xmpp.c.

726{
727 if (state == client->state) {
728 return;
729 }
730 client->state = state;
731 if (client->state == XMPP_STATE_DISCONNECTED) {
733 } else if (client->state == XMPP_STATE_CONNECTED) {
735 }
736}
enum cc_state state
Definition: ccss.c:399
@ AST_ENDPOINT_OFFLINE
Definition: endpoints.h:55
@ AST_ENDPOINT_ONLINE
Definition: endpoints.h:57
void ast_endpoint_set_state(struct ast_endpoint *endpoint, enum ast_endpoint_state state)
Updates the state of the given endpoint.
@ XMPP_STATE_CONNECTED
Definition: xmpp.h:80

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

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

◆ xmpp_client_config_merge_buddies()

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

Definition at line 3937 of file res_xmpp.c.

3938{
3939 struct ast_xmpp_buddy *buddy1 = obj, *buddy2;
3940 struct ao2_container *buddies = arg;
3941
3942 /* If the buddy does not already exist link it into the client buddies container */
3943 if (!(buddy2 = ao2_find(buddies, buddy1->id, OBJ_KEY))) {
3944 ao2_link(buddies, buddy1);
3945 } else {
3946 ao2_ref(buddy2, -1);
3947 }
3948
3949 /* All buddies are unlinked from the configuration buddies container, always */
3950 return 1;
3951}
#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 3992 of file res_xmpp.c.

3993{
3994 struct ast_xmpp_client_config *cfg = obj;
3996
3997 /* Merge global options that have not been modified */
3998 ast_copy_flags(&cfg->flags, &gcfg->global->general, ~(cfg->mod_flags.flags) & (XMPP_AUTOPRUNE | XMPP_AUTOREGISTER | XMPP_AUTOACCEPT));
3999
4000 /* Merge buddies as need be */
4002
4003 if (cfg->client->reconnect) {
4004 /* Disconnect the existing session since our role is changing, or we are starting up */
4006
4007 if (!(cfg->client->parser = iks_stream_new(ast_test_flag(&cfg->flags, XMPP_COMPONENT) ? "jabber:component:accept" : "jabber:client", cfg->client,
4008 xmpp_action_hook))) {
4009 ast_log(LOG_ERROR, "Iksemel stream could not be created for client '%s' - client not active\n", cfg->name);
4010 return -1;
4011 }
4012
4013 iks_set_log_hook(cfg->client->parser, xmpp_log_hook);
4014
4015 /* Create a JID based on the given user, if no resource is given use the default */
4016 if (!strchr(cfg->user, '/') && !ast_test_flag(&cfg->flags, XMPP_COMPONENT)) {
4017 char resource[strlen(cfg->user) + strlen("/asterisk-xmpp") + 1];
4018
4019 snprintf(resource, sizeof(resource), "%s/asterisk-xmpp", cfg->user);
4020 cfg->client->jid = iks_id_new(cfg->client->stack, resource);
4021 } else {
4022 cfg->client->jid = iks_id_new(cfg->client->stack, cfg->user);
4023 }
4024
4025 if (!cfg->client->jid || (ast_strlen_zero(cfg->client->jid->user) && !ast_test_flag(&cfg->flags, XMPP_COMPONENT))) {
4026 ast_log(LOG_ERROR, "Jabber identity '%s' could not be created for client '%s' - client not active\n", cfg->user, cfg->name);
4027 return -1;
4028 }
4029
4031
4032 cfg->client->reconnect = 0;
4033 } else if (cfg->client->state == XMPP_STATE_CONNECTED) {
4034 /* If this client is connected update their presence status since it may have changed */
4035 xmpp_client_set_presence(cfg->client, NULL, cfg->client->jid->full, cfg->status, cfg->statusmsg);
4036
4037 /* Subscribe to the status of any newly added buddies */
4040 }
4041 }
4042
4043 return 0;
4044}
@ 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:3937
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:2434
int ast_xmpp_client_disconnect(struct ast_xmpp_client *client)
Disconnect an XMPP client connection.
Definition: res_xmpp.c:3654
static void * xmpp_client_thread(void *data)
XMPP client connection thread.
Definition: res_xmpp.c:3857
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:2355
static int xmpp_action_hook(void *data, int type, iks *node)
Action hook for when things occur.
Definition: res_xmpp.c:3584
static void xmpp_log_hook(void *data, const char *xmpp, size_t size, int incoming)
Logging hook function.
Definition: res_xmpp.c:2600
unsigned int flags
Definition: utils.h:200
const ast_string_field user
Definition: res_xmpp.c:591
const ast_string_field statusmsg
Definition: res_xmpp.c:591
unsigned int reconnect
Definition: xmpp.h:142
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84

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

Referenced by xmpp_config_post_apply().

◆ xmpp_client_create_buddy()

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

Internal function which creates a buddy on a client.

Definition at line 2292 of file res_xmpp.c.

2293{
2294 struct ast_xmpp_buddy *buddy;
2295
2296 if (!(buddy = ao2_alloc(sizeof(*buddy), xmpp_buddy_destructor))) {
2297 return NULL;
2298 }
2299
2302 if (!buddy->resources) {
2303 ao2_ref(buddy, -1);
2304 return NULL;
2305 }
2306
2307 ast_copy_string(buddy->id, id, sizeof(buddy->id));
2308
2309 /* Assume we need to subscribe to get their presence until proven otherwise */
2310 buddy->subscribe = 1;
2311
2312 ao2_link(container, buddy);
2313
2314 return buddy;
2315}
struct ao2_container * container
Definition: res_fax.c:531
#define RESOURCE_BUCKETS
Number of buckets for resources (per buddy)
Definition: res_xmpp.c:561
static int xmpp_resource_hash(const void *obj, const int flags)
Hashing function for XMPP resource.
Definition: res_xmpp.c:974
static void xmpp_buddy_destructor(void *obj)
Destructor callback function for XMPP buddy.
Definition: res_xmpp.c:991
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 680 of file res_xmpp.c.

681{
682 struct ast_xmpp_client *client = obj;
684
686
688 client->endpoint = NULL;
689
690 if (client->filter) {
691 iks_filter_delete(client->filter);
692 }
693
694 if (client->stack) {
695 iks_stack_delete(client->stack);
696 }
697
698 ao2_cleanup(client->buddies);
699
700 while ((message = AST_LIST_REMOVE_HEAD(&client->messages, list))) {
702 }
704}
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 792 of file res_xmpp.c.

793{
795 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
796
797 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, category))) {
798 return xmpp_client_alloc(category);
799 }
800
801 ao2_ref(clientcfg->client, +1);
802 return clientcfg->client;
803}
static struct ast_xmpp_client * xmpp_client_alloc(const char *name)
Allocator function for ast_xmpp_client.
Definition: res_xmpp.c:739

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 3777 of file res_xmpp.c.

3778{
3779 int len, ret, pos = 0, newbufpos = 0;
3780 char buf[NET_IO_BUF_SIZE - 1] = "";
3781 char newbuf[NET_IO_BUF_SIZE - 1] = "";
3782 unsigned char c;
3783
3784 while (1) {
3785 len = xmpp_io_recv(client, buf, NET_IO_BUF_SIZE - 2, timeout);
3786 if (len < 0) return IKS_NET_RWERR;
3787 if (len == 0) return IKS_NET_EXPIRED;
3788 buf[len] = '\0';
3789
3790 /* our iksemel parser won't work as expected if we feed
3791 it with XML packets that contain multiple whitespace
3792 characters between tags */
3793 while (pos < len) {
3794 c = buf[pos];
3795 /* if we stumble on the ending tag character,
3796 we skip any whitespace that follows it*/
3797 if (c == '>') {
3798 while (isspace(buf[pos+1])) {
3799 pos++;
3800 }
3801 }
3802 newbuf[newbufpos] = c;
3803 newbufpos++;
3804 pos++;
3805 }
3806 pos = 0;
3807 newbufpos = 0;
3808
3809 /* Log the message here, because iksemel's logHook is
3810 unaccessible */
3811 xmpp_log_hook(client, buf, len, 1);
3812
3813 if(buf[0] == ' ') {
3814 ast_debug(1, "JABBER: Detected Google Keep Alive. "
3815 "Sending out Ping request for client '%s'\n", client->name);
3816 /* If we just send out the ping here then we will have socket
3817 * read errors because the socket will timeout */
3818 xmpp_ping_request(client, client->jid->server, client->jid->full);
3819 }
3820
3821 /* let iksemel deal with the string length,
3822 and reset our buffer */
3823 ret = iks_parse(client->parser, newbuf, 0, 0);
3824 memset(newbuf, 0, sizeof(newbuf));
3825
3826 switch (ret) {
3827 case IKS_NOMEM:
3828 ast_log(LOG_WARNING, "Parsing failure: Out of memory.\n");
3829 break;
3830 case IKS_BADXML:
3831 ast_log(LOG_WARNING, "Parsing failure: Invalid XML.\n");
3832 break;
3833 case IKS_HOOK:
3834 ast_log(LOG_WARNING, "Parsing failure: Hook returned an error.\n");
3835 break;
3836 }
3837 if (ret != IKS_OK) {
3838 return ret;
3839 }
3840 ast_debug(3, "XML parsing successful\n");
3841 }
3842 return IKS_OK;
3843}
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:3358
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:3743
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, 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 3693 of file res_xmpp.c.

3694{
3695 struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
3697 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3698 int res = IKS_NET_NOCONN;
3699
3700 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
3701 return -1;
3702 }
3703
3705
3706 client->timeout = 50;
3707 iks_parser_reset(client->parser);
3708
3709 if (!client->filter && !(client->filter = iks_filter_new())) {
3710 ast_log(LOG_ERROR, "Could not create IKS filter for client connection '%s'\n", client->name);
3711 return -1;
3712 }
3713
3714 if (!ast_strlen_zero(clientcfg->refresh_token)) {
3715 ast_debug(2, "Obtaining OAuth access token for client '%s'\n", client->name);
3716 if (fetch_access_token(clientcfg)) {
3717 return -1;
3718 }
3719 }
3720
3721 /* If it's a component connect to user otherwise connect to server */
3722 res = iks_connect_via(client->parser, S_OR(clientcfg->server, client->jid->server), clientcfg->port,
3723 ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) ? clientcfg->user : client->jid->server);
3724
3725 /* Set socket timeout options */
3726 setsockopt(iks_fd(client->parser), SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
3727
3728 if (res == IKS_NET_NOCONN) {
3729 ast_log(LOG_ERROR, "No XMPP connection available when trying to connect client '%s'\n", client->name);
3730 return -1;
3731 } else if (res == IKS_NET_NODNS) {
3732 ast_log(LOG_ERROR, "No DNS available for XMPP connection when trying to connect client '%s'\n", client->name);
3733 return -1;
3734 }
3735
3736 /* Depending on the configuration of the client we eiher jump to requesting TLS, or authenticating */
3738
3739 return 0;
3740}
static int fetch_access_token(struct ast_xmpp_client_config *cfg)
Definition: res_xmpp.c:3953
#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 2669 of file res_xmpp.c.

2670{
2671 /* If the client connection is already secure we can jump straight to authenticating */
2672 if (xmpp_is_secure(client)) {
2674 return 0;
2675 }
2676
2677#ifndef HAVE_OPENSSL
2678 ast_log(LOG_ERROR, "TLS connection for client '%s' cannot be established. OpenSSL is not available.\n", client->name);
2679 return -1;
2680#else
2681 if (iks_send_raw(client->parser, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>") == IKS_NET_TLSFAIL) {
2682 ast_log(LOG_ERROR, "TLS connection for client '%s' cannot be started.\n", client->name);
2683 return -1;
2684 }
2685
2686 client->stream_flags |= TRY_SECURE;
2687
2689
2690 return 0;
2691#endif
2692}
@ 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 2713 of file res_xmpp.c.

2714{
2715#ifdef HAVE_OPENSSL
2716 int sock;
2717 long ssl_opts;
2718 char *err;
2719#endif
2720
2721 if (!strcmp(iks_name(node), "success")) {
2722 /* TLS is up and working, we can move on to authenticating now */
2724 return 0;
2725 } else if (!strcmp(iks_name(node), "failure")) {
2726 /* TLS negotiation was a failure, close it on down! */
2727 return -1;
2728 } else if (strcmp(iks_name(node), "proceed")) {
2729 /* Ignore any other responses */
2730 return 0;
2731 }
2732
2733#ifndef HAVE_OPENSSL
2734 ast_log(LOG_ERROR, "Somehow we managed to try to start TLS negotiation on client '%s' without OpenSSL support, disconnecting\n", client->name);
2735 return -1;
2736#else
2737 client->ssl_method = SSLv23_method();
2738 if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) {
2739 goto failure;
2740 }
2741
2742 ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
2743 SSL_CTX_set_options(client->ssl_context, ssl_opts);
2744
2745 if (!(client->ssl_session = SSL_new(client->ssl_context))) {
2746 goto failure;
2747 }
2748
2749 sock = iks_fd(client->parser);
2750 if (!SSL_set_fd(client->ssl_session, sock)) {
2751 goto failure;
2752 }
2753
2754 if (SSL_connect(client->ssl_session) <= 0) {
2755 goto failure;
2756 }
2757
2758 client->stream_flags &= (~TRY_SECURE);
2759 client->stream_flags |= SECURE;
2760
2761 if (xmpp_send_stream_header(client, cfg, client->jid->server) != IKS_OK) {
2762 ast_log(LOG_ERROR, "TLS connection for client '%s' could not be established, failed to send stream header after negotiation\n",
2763 client->name);
2764 return -1;
2765 }
2766
2767 ast_debug(1, "TLS connection for client '%s' started with server\n", client->name);
2768
2770
2771 return 0;
2772
2773failure:
2774 err = openssl_error_string();
2775 ast_log(LOG_ERROR, "TLS connection for client '%s' cannot be established. "
2776 "OpenSSL initialization failed: %s\n", client->name, err);
2777 ast_free(err);
2778 return -1;
2779#endif
2780}

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 3321 of file res_xmpp.c.

3322{
3323 iks *iq, *query;
3324 int res;
3325
3326 if (!(iq = iks_new("iq")) || !(query = iks_new("query"))) {
3327 iks_delete(iq);
3328 return -1;
3329 }
3330
3331 iks_insert_attrib(iq, "type", "get");
3332 iks_insert_attrib(iq, "to", to);
3333 iks_insert_attrib(iq, "from", from);
3334 ast_xmpp_client_lock(client);
3335 iks_insert_attrib(iq, "id", client->mid);
3336 ast_xmpp_increment_mid(client->mid);
3337 ast_xmpp_client_unlock(client);
3338 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
3339 iks_insert_node(iq, query);
3340
3341 res = ast_xmpp_client_send(client, iq);
3342
3343 iks_delete(query);
3344 iks_delete(iq);
3345
3346 return res;
3347}

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 1039 of file res_xmpp.c.

1040{
1042 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1043 int res = 0;
1044 char from[XMPP_MAX_JIDLEN];
1045 iks *message_packet;
1046
1047 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
1048 !(message_packet = iks_make_msg(group ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message))) {
1049 return -1;
1050 }
1051
1052 if (!ast_strlen_zero(nick) && ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1053 snprintf(from, sizeof(from), "%s@%s/%s", nick, client->jid->full, nick);
1054 } else {
1055 snprintf(from, sizeof(from), "%s", client->jid->full);
1056 }
1057
1058 iks_insert_attrib(message_packet, "from", from);
1059
1060 res = ast_xmpp_client_send(client, message_packet);
1061
1062 iks_delete(message_packet);
1063
1064 return res;
1065}

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 2618 of file res_xmpp.c.

2619{
2620 int ret;
2621
2622 if (client->state == XMPP_STATE_DISCONNECTED) {
2623 /* iks_send_raw will crash without a connection */
2624 return IKS_NET_NOCONN;
2625 }
2626
2627#ifdef HAVE_OPENSSL
2628 if (xmpp_is_secure(client)) {
2629 int len = strlen(message);
2630
2631 ret = SSL_write(client->ssl_session, message, len);
2632 if (ret) {
2633 /* Log the message here, because iksemel's logHook is
2634 unaccessible */
2635 xmpp_log_hook(client, message, len, 0);
2636 return IKS_OK;
2637 }
2638 }
2639#endif
2640 /* If needed, data will be sent unencrypted, and logHook will
2641 be called inside iks_send_raw */
2642 ret = iks_send_raw(client->parser, message);
2643 if (ret != IKS_OK) {
2644 return ret;
2645 }
2646
2647 return IKS_OK;
2648}

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 2472 of file res_xmpp.c.

2473{
2474 struct ast_xmpp_client *client = data;
2475 iks *iq, *disco = NULL, *ident = NULL, *google = NULL, *jingle = NULL, *ice = NULL, *rtp = NULL, *audio = NULL, *video = NULL, *query = NULL;
2476
2477 if (!(iq = iks_new("iq")) || !(query = iks_new("query")) || !(ident = iks_new("identity")) || !(disco = iks_new("feature")) ||
2478 !(google = iks_new("feature")) || !(jingle = iks_new("feature")) || !(ice = iks_new("feature")) || !(rtp = iks_new("feature")) ||
2479 !(audio = iks_new("feature")) || !(video = iks_new("feature"))) {
2480 ast_log(LOG_ERROR, "Could not allocate memory for responding to service discovery request from '%s' on client '%s'\n",
2481 pak->from->full, client->name);
2482 goto end;
2483 }
2484
2485 iks_insert_attrib(iq, "from", client->jid->full);
2486
2487 if (pak->from) {
2488 iks_insert_attrib(iq, "to", pak->from->full);
2489 }
2490
2491 iks_insert_attrib(iq, "type", "result");
2492 iks_insert_attrib(iq, "id", pak->id);
2493 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
2494 iks_insert_attrib(ident, "category", "client");
2495 iks_insert_attrib(ident, "type", "pc");
2496 iks_insert_attrib(ident, "name", "asterisk");
2497 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco#info");
2498
2499 iks_insert_attrib(google, "var", "http://www.google.com/xmpp/protocol/voice/v1");
2500 iks_insert_attrib(jingle, "var", "urn:xmpp:jingle:1");
2501 iks_insert_attrib(ice, "var", "urn:xmpp:jingle:transports:ice-udp:1");
2502 iks_insert_attrib(rtp, "var", "urn:xmpp:jingle:apps:rtp:1");
2503 iks_insert_attrib(audio, "var", "urn:xmpp:jingle:apps:rtp:audio");
2504 iks_insert_attrib(video, "var", "urn:xmpp:jingle:apps:rtp:video");
2505 iks_insert_node(iq, query);
2506 iks_insert_node(query, ident);
2507 iks_insert_node(query, google);
2508 iks_insert_node(query, disco);
2509 iks_insert_node(query, jingle);
2510 iks_insert_node(query, ice);
2511 iks_insert_node(query, rtp);
2512 iks_insert_node(query, audio);
2513 iks_insert_node(query, video);
2514 ast_xmpp_client_send(client, iq);
2515
2516end:
2517 iks_delete(query);
2518 iks_delete(video);
2519 iks_delete(audio);
2520 iks_delete(rtp);
2521 iks_delete(ice);
2522 iks_delete(jingle);
2523 iks_delete(google);
2524 iks_delete(ident);
2525 iks_delete(disco);
2526 iks_delete(iq);
2527
2528 return IKS_FILTER_EAT;
2529}
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 2532 of file res_xmpp.c.

2533{
2534 struct ast_xmpp_client *client = data;
2535 struct ast_xmpp_buddy *buddy;
2537
2538 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY))) {
2539 return IKS_FILTER_EAT;
2540 }
2541
2542 if (!(resource = ao2_callback(buddy->resources, 0, xmpp_resource_cmp, pak->from->resource))) {
2543 ao2_ref(buddy, -1);
2544 return IKS_FILTER_EAT;
2545 }
2546
2548
2549 if (iks_find_with_attrib(pak->query, "feature", "var", "urn:xmpp:jingle:1")) {
2550 resource->caps.jingle = 1;
2551 }
2552
2554
2555 ao2_ref(resource, -1);
2556 ao2_ref(buddy, -1);
2557
2558 return IKS_FILTER_EAT;
2559}
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 1103 of file res_xmpp.c.

1104{
1106 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1107 int res = 0;
1108 iks *presence = NULL, *x = NULL;
1109 char from[XMPP_MAX_JIDLEN], roomid[XMPP_MAX_JIDLEN];
1110
1111 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
1112 !(presence = iks_make_pres(level, NULL)) || !(x = iks_new("x"))) {
1113 res = -1;
1114 goto done;
1115 }
1116
1117 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1118 snprintf(from, sizeof(from), "%s@%s/%s", nick, client->jid->full, nick);
1119 snprintf(roomid, sizeof(roomid), "%s/%s", room, nick);
1120 } else {
1121 snprintf(from, sizeof(from), "%s", client->jid->full);
1122 snprintf(roomid, sizeof(roomid), "%s/%s", room, S_OR(nick, client->jid->user));
1123 }
1124
1125 iks_insert_attrib(presence, "to", roomid);
1126 iks_insert_attrib(presence, "from", from);
1127 iks_insert_attrib(x, "xmlns", "http://jabber.org/protocol/muc");
1128 iks_insert_node(presence, x);
1129
1130 res = ast_xmpp_client_send(client, presence);
1131
1132done:
1133 iks_delete(x);
1134 iks_delete(presence);
1135
1136 return res;
1137}

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 2434 of file res_xmpp.c.

2435{
2437 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2438 iks *presence = NULL, *cnode = NULL, *priority = NULL;
2439 char priorityS[10];
2440
2441 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
2442 !(presence = iks_make_pres(level, desc)) || !(cnode = iks_new("c")) || !(priority = iks_new("priority"))) {
2443 ast_log(LOG_ERROR, "Unable to allocate stanzas for setting presence status for client '%s'\n", client->name);
2444 goto done;
2445 }
2446
2447 if (!ast_strlen_zero(to)) {
2448 iks_insert_attrib(presence, "to", to);
2449 }
2450
2451 if (!ast_strlen_zero(from)) {
2452 iks_insert_attrib(presence, "from", from);
2453 }
2454
2455 snprintf(priorityS, sizeof(priorityS), "%d", clientcfg->priority);
2456 iks_insert_cdata(priority, priorityS, strlen(priorityS));
2457 iks_insert_node(presence, priority);
2458 iks_insert_attrib(cnode, "node", "http://www.asterisk.org/xmpp/client/caps");
2459 iks_insert_attrib(cnode, "ver", "asterisk-xmpp");
2460 iks_insert_attrib(cnode, "ext", "voice-v1 video-v1 camera-v1");
2461 iks_insert_attrib(cnode, "xmlns", "http://jabber.org/protocol/caps");
2462 iks_insert_node(presence, cnode);
2463 ast_xmpp_client_send(client, presence);
2464
2465done:
2466 iks_delete(cnode);
2467 iks_delete(presence);
2468 iks_delete(priority);
2469}
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 2355 of file res_xmpp.c.

2356{
2357 struct ast_xmpp_buddy *buddy = obj;
2358 struct ast_xmpp_client *client = arg;
2359
2360 if (!buddy->subscribe) {
2361 return 0;
2362 }
2363
2364 if (ast_xmpp_client_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, buddy->id,
2365 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"))) {
2366 ast_log(LOG_WARNING, "Could not send subscription for '%s' on client '%s'\n",
2367 buddy->id, client->name);
2368 }
2369
2370 buddy->subscribe = 0;
2371
2372 return 0;
2373}

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 3857 of file res_xmpp.c.

3858{
3859 struct ast_xmpp_client *client = data;
3860 int res = IKS_NET_RWERR;
3861 unsigned int sleep_time = 1;
3862
3863 /* We only allow cancellation while sleeping */
3864 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
3865
3866 do {
3867 if (client->state == XMPP_STATE_DISCONNECTING) {
3868 ast_debug(1, "[%s] Disconnecting\n", client->name);
3869 break;
3870 }
3871
3872 if (res == IKS_NET_RWERR || client->timeout == 0) {
3873 ast_debug(3, "[%s] Connecting\n", client->name);
3874 if ((res = xmpp_client_reconnect(client)) != IKS_OK) {
3875 sleep_with_backoff(&sleep_time);
3876 res = IKS_NET_RWERR;
3877 }
3878 continue;
3879 }
3880
3881 res = xmpp_client_receive(client, 1);
3882
3883 /* Decrease timeout if no data received, and delete
3884 * old messages globally */
3885 if (res == IKS_NET_EXPIRED) {
3886 client->timeout--;
3887 }
3888
3889 if (res == IKS_HOOK) {
3890 ast_debug(2, "[%s] Got hook event\n", client->name);
3891 } else if (res == IKS_NET_TLSFAIL) {
3892 ast_log(LOG_ERROR, "[%s] TLS failure\n", client->name);
3893 } else if (!client->timeout && client->state == XMPP_STATE_CONNECTED) {
3895 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3896
3897 if (cfg && cfg->clients) {
3898 clientcfg = xmpp_config_find(cfg->clients, client->name);
3899 }
3900
3901 if (clientcfg && ast_test_flag(&clientcfg->flags, XMPP_KEEPALIVE)) {
3902 res = xmpp_ping_request(client, client->jid->server, client->jid->full);
3903 } else {
3904 res = IKS_OK;
3905 }
3906
3907 if (res == IKS_OK) {
3908 client->timeout = 50;
3909 } else {
3910 ast_log(LOG_WARNING, "[%s] Network timeout\n", client->name);
3911 }
3912 } else if (res == IKS_NET_RWERR) {
3913 ast_log(LOG_WARNING, "[%s] Socket read error\n", client->name);
3915 sleep_with_backoff(&sleep_time);
3916 } else if (res == IKS_NET_NOSOCK) {
3917 ast_log(LOG_WARNING, "[%s] No socket\n", client->name);
3918 } else if (res == IKS_NET_NOCONN) {
3919 ast_log(LOG_WARNING, "[%s] No connection\n", client->name);
3920 } else if (res == IKS_NET_NODNS) {
3921 ast_log(LOG_WARNING, "[%s] No DNS\n", client->name);
3922 } else if (res == IKS_NET_NOTSUPP) {
3923 ast_log(LOG_WARNING, "[%s] Not supported\n", client->name);
3924 } else if (res == IKS_NET_DROPPED) {
3925 ast_log(LOG_WARNING, "[%s] Dropped?\n", client->name);
3926 } else if (res == IKS_NET_UNKNOWN) {
3927 ast_debug(5, "[%s] Unknown\n", client->name);
3928 } else if (res == IKS_OK) {
3929 sleep_time = 1;
3930 }
3931
3932 } while (1);
3933
3934 return NULL;
3935}
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:3693
static void sleep_with_backoff(unsigned int *sleep_time)
Definition: res_xmpp.c:3845
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:3777

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 2318 of file res_xmpp.c.

2319{
2320 iks *iq, *query = NULL, *item = NULL;
2321
2322 if (ast_xmpp_client_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, user,
2323 "Goodbye. Your status is no longer required.\n"))) {
2324 return -1;
2325 }
2326
2327 if (!(iq = iks_new("iq")) || !(query = iks_new("query")) || !(item = iks_new("item"))) {
2328 ast_log(LOG_WARNING, "Could not allocate memory for roster removal of '%s' from client '%s'\n",
2329 user, client->name);
2330 goto done;
2331 }
2332
2333 iks_insert_attrib(iq, "from", client->jid->full);
2334 iks_insert_attrib(iq, "type", "set");
2335 iks_insert_attrib(query, "xmlns", "jabber:iq:roster");
2336 iks_insert_node(iq, query);
2337 iks_insert_attrib(item, "jid", user);
2338 iks_insert_attrib(item, "subscription", "remove");
2339 iks_insert_node(query, item);
2340
2341 if (ast_xmpp_client_send(client, iq)) {
2342 ast_log(LOG_WARNING, "Could not send roster removal request of '%s' from client '%s'\n",
2343 user, client->name);
2344 }
2345
2346done:
2347 iks_delete(item);
2348 iks_delete(query);
2349 iks_delete(iq);
2350
2351 return 0;
2352}
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 2953 of file res_xmpp.c.

2954{
2955 char secret[160], shasum[320], message[344];
2956 ikspak *pak = iks_packet(node);
2957
2958 snprintf(secret, sizeof(secret), "%s%s", pak->id, cfg->password);
2959 ast_sha1_hash(shasum, secret);
2960 snprintf(message, sizeof(message), "<handshake>%s</handshake>", shasum);
2961
2962 if (xmpp_client_send_raw_message(client, message) != IKS_OK) {
2963 ast_log(LOG_ERROR, "Unable to send handshake for component '%s'\n", client->name);
2964 return -1;
2965 }
2966
2968
2969 return 0;
2970}

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 3219 of file res_xmpp.c.

3220{
3221 if (!strcmp(iks_name(node), "stream:features")) {
3222 return 0;
3223 }
3224
3225 if (strcmp(iks_name(node), "handshake")) {
3226 ast_log(LOG_ERROR, "Failed to authenticate component '%s'\n", client->name);
3227 return -1;
3228 }
3229
3230 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);
3231
3232 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);
3233
3234 /* This uses the client service discovery result hook on purpose, as the code is common between both */
3235 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);
3236
3237 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);
3238 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);
3239
3241
3242 return 0;
3243}
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:3060
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:2532
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:3168
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:2973
static int xmpp_component_register_set_hook(void *data, ikspak *pak)
Hook function called when someone registers to the component.
Definition: res_xmpp.c:3121

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 3060 of file res_xmpp.c.

3061{
3063 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3064 struct ast_xmpp_client *client = data;
3065 iks *iq = NULL, *query = NULL, *error = NULL, *notacceptable = NULL, *instructions = NULL;
3066 struct ast_xmpp_buddy *buddy;
3067 char *node;
3068
3069 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
3070 !(iq = iks_new("iq")) || !(query = iks_new("query")) || !(error = iks_new("error")) || !(notacceptable = iks_new("not-acceptable")) ||
3071 !(instructions = iks_new("instructions"))) {
3072 ast_log(LOG_ERROR, "Failed to allocate stanzas for register get response to '%s' on component '%s'\n",
3073 pak->from->partial, client->name);
3074 goto done;
3075 }
3076
3077 iks_insert_attrib(iq, "from", clientcfg->user);
3078 iks_insert_attrib(iq, "to", pak->from->full);
3079 iks_insert_attrib(iq, "id", pak->id);
3080 iks_insert_attrib(iq, "type", "result");
3081 iks_insert_attrib(query, "xmlns", "jabber:iq:register");
3082 iks_insert_node(iq, query);
3083
3084 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY))) {
3085 iks_insert_attrib(error, "code", "406");
3086 iks_insert_attrib(error, "type", "modify");
3087 iks_insert_attrib(notacceptable, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
3088
3089 iks_insert_node(iq, error);
3090 iks_insert_node(error, notacceptable);
3091
3092 ast_log(LOG_ERROR, "Received register attempt from '%s' but buddy is not configured on component '%s'\n",
3093 pak->from->partial, client->name);
3094 } else if (!(node = iks_find_attrib(pak->query, "node"))) {
3095 iks_insert_cdata(instructions, "Welcome to Asterisk - the Open Source PBX.\n", 0);
3096 iks_insert_node(query, instructions);
3097 ao2_ref(buddy, -1);
3098 } else {
3099 ast_log(LOG_WARNING, "Received register get to component '%s' using unsupported node '%s' from '%s'\n",
3100 client->name, node, pak->from->partial);
3101 ao2_ref(buddy, -1);
3102 goto done;
3103 }
3104
3105 if (ast_xmpp_client_send(client, iq)) {
3106 ast_log(LOG_WARNING, "Could not send response to '%s' for received register get on component '%s'\n",
3107 pak->from->partial, client->name);
3108 }
3109
3110done:
3111 iks_delete(instructions);
3112 iks_delete(notacceptable);
3113 iks_delete(error);
3114 iks_delete(query);
3115 iks_delete(iq);
3116
3117 return IKS_FILTER_EAT;
3118}

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 3121 of file res_xmpp.c.

3122{
3123 struct ast_xmpp_client *client = data;
3124 iks *iq, *presence = NULL, *x = NULL;
3125
3126 if (!(iq = iks_new("iq")) || !(presence = iks_new("presence")) || !(x = iks_new("x"))) {
3127 ast_log(LOG_ERROR, "Failed to allocate stanzas for register set response to '%s' on component '%s'\n",
3128 pak->from->partial, client->name);
3129 goto done;
3130 }
3131
3132 iks_insert_attrib(iq, "from", client->jid->full);
3133 iks_insert_attrib(iq, "to", pak->from->full);
3134 iks_insert_attrib(iq, "id", pak->id);
3135 iks_insert_attrib(iq, "type", "result");
3136
3137 if (ast_xmpp_client_send(client, iq)) {
3138 ast_log(LOG_WARNING, "Could not send response to '%s' for received register set on component '%s'\n",
3139 pak->from->partial, client->name);
3140 goto done;
3141 }
3142
3143 iks_insert_attrib(presence, "from", client->jid->full);
3144 iks_insert_attrib(presence, "to", pak->from->partial);
3145 ast_xmpp_client_lock(client);
3146 iks_insert_attrib(presence, "id", client->mid);
3147 ast_xmpp_increment_mid(client->mid);
3148 ast_xmpp_client_unlock(client);
3149 iks_insert_attrib(presence, "type", "subscribe");
3150 iks_insert_attrib(x, "xmlns", "vcard-temp:x:update");
3151
3152 iks_insert_node(presence, x);
3153
3154 if (ast_xmpp_client_send(client, presence)) {
3155 ast_log(LOG_WARNING, "Could not send subscription to '%s' on component '%s'\n",
3156 pak->from->partial, client->name);
3157 }
3158
3159done:
3160 iks_delete(x);
3161 iks_delete(presence);
3162 iks_delete(iq);
3163
3164 return IKS_FILTER_EAT;
3165}

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 2973 of file res_xmpp.c.

2974{
2976 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2977 struct ast_xmpp_client *client = data;
2978 iks *iq = NULL, *query = NULL, *identity = NULL, *disco = NULL, *reg = NULL, *commands = NULL, *gateway = NULL;
2979 iks *version = NULL, *vcard = NULL, *search = NULL, *item = NULL;
2980 char *node;
2981
2982 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
2983 !(iq = iks_new("iq")) || !(query = iks_new("query")) || !(identity = iks_new("identity")) || !(disco = iks_new("feature")) ||
2984 !(reg = iks_new("feature")) || !(commands = iks_new("feature")) || !(gateway = iks_new("feature")) || !(version = iks_new("feature")) ||
2985 !(vcard = iks_new("feature")) || !(search = iks_new("search")) || !(item = iks_new("item"))) {
2986 ast_log(LOG_ERROR, "Failed to allocate stanzas for service discovery get response to '%s' on component '%s'\n",
2987 pak->from->partial, client->name);
2988 goto done;
2989 }
2990
2991 iks_insert_attrib(iq, "from", clientcfg->user);
2992 iks_insert_attrib(iq, "to", pak->from->full);
2993 iks_insert_attrib(iq, "id", pak->id);
2994 iks_insert_attrib(iq, "type", "result");
2995
2996 if (!(node = iks_find_attrib(pak->query, "node"))) {
2997 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
2998 iks_insert_attrib(identity, "category", "gateway");
2999 iks_insert_attrib(identity, "type", "pstn");
3000 iks_insert_attrib(identity, "name", "Asterisk The Open Source PBX");
3001 iks_insert_attrib(disco, "var", "http://jabber.org/protocol/disco");
3002 iks_insert_attrib(reg, "var", "jabber:iq:register");
3003 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
3004 iks_insert_attrib(gateway, "var", "jabber:iq:gateway");
3005 iks_insert_attrib(version, "var", "jabber:iq:version");
3006 iks_insert_attrib(vcard, "var", "vcard-temp");
3007 iks_insert_attrib(search, "var", "jabber:iq:search");
3008
3009 iks_insert_node(iq, query);
3010 iks_insert_node(query, identity);
3011 iks_insert_node(query, disco);
3012 iks_insert_node(query, reg);
3013 iks_insert_node(query, commands);
3014 iks_insert_node(query, gateway);
3015 iks_insert_node(query, version);
3016 iks_insert_node(query, vcard);
3017 iks_insert_node(query, search);
3018 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
3019 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
3020 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
3021 iks_insert_attrib(item, "node", "confirmaccount");
3022 iks_insert_attrib(item, "name", "Confirm account");
3023 iks_insert_attrib(item, "jid", clientcfg->user);
3024
3025 iks_insert_node(iq, query);
3026 iks_insert_node(query, item);
3027 } else if (!strcasecmp(node, "confirmaccount")) {
3028 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
3029 iks_insert_attrib(commands, "var", "http://jabber.org/protocol/commands");
3030
3031 iks_insert_node(iq, query);
3032 iks_insert_node(query, commands);
3033 } else {
3034 ast_debug(3, "Unsupported service discovery info request received with node '%s' on component '%s'\n",
3035 node, client->name);
3036 goto done;
3037 }
3038
3039 if (ast_xmpp_client_send(client, iq)) {
3040 ast_log(LOG_WARNING, "Could not send response to service discovery request on component '%s'\n",
3041 client->name);
3042 }
3043
3044done:
3045 iks_delete(search);
3046 iks_delete(vcard);
3047 iks_delete(version);
3048 iks_delete(gateway);
3049 iks_delete(commands);
3050 iks_delete(reg);
3051 iks_delete(disco);
3052 iks_delete(identity);
3053 iks_delete(query);
3054 iks_delete(iq);
3055
3056 return IKS_FILTER_EAT;
3057}
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3911

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 3168 of file res_xmpp.c.

3169{
3171 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
3172 struct ast_xmpp_client *client = data;
3173 iks *iq = NULL, *query = NULL, *item = NULL, *feature = NULL;
3174 char *node;
3175
3176 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
3177 !(iq = iks_new("iq")) || !(query = iks_new("query")) || !(item = iks_new("item")) || !(feature = iks_new("feature"))) {
3178 ast_log(LOG_ERROR, "Failed to allocate stanzas for service discovery items response to '%s' on component '%s'\n",
3179 pak->from->partial, client->name);
3180 goto done;
3181 }
3182
3183 iks_insert_attrib(iq, "from", clientcfg->user);
3184 iks_insert_attrib(iq, "to", pak->from->full);
3185 iks_insert_attrib(iq, "id", pak->id);
3186 iks_insert_attrib(iq, "type", "result");
3187 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
3188 iks_insert_node(iq, query);
3189
3190 if (!(node = iks_find_attrib(pak->query, "node"))) {
3191 iks_insert_attrib(item, "node", "http://jabber.org/protocol/commands");
3192 iks_insert_attrib(item, "name", "Asterisk Commands");
3193 iks_insert_attrib(item, "jid", clientcfg->user);
3194
3195 iks_insert_node(query, item);
3196 } else if (!strcasecmp(node, "http://jabber.org/protocol/commands")) {
3197 iks_insert_attrib(query, "node", "http://jabber.org/protocol/commands");
3198 } else {
3199 ast_log(LOG_WARNING, "Received service discovery items request to component '%s' using unsupported node '%s' from '%s'\n",
3200 client->name, node, pak->from->partial);
3201 goto done;
3202 }
3203
3204 if (ast_xmpp_client_send(client, iq)) {
3205 ast_log(LOG_WARNING, "Could not send response to service discovery items request from '%s' on component '%s'\n",
3206 pak->from->partial, client->name);
3207 }
3208
3209done:
3210 iks_delete(feature);
3211 iks_delete(item);
3212 iks_delete(query);
3213 iks_delete(iq);
3214
3215 return IKS_FILTER_EAT;
3216}

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 853 of file res_xmpp.c.

854{
855 struct xmpp_config *cfg;
856
857 if (!(cfg = ao2_alloc(sizeof(*cfg), xmpp_config_destructor))) {
858 return NULL;
859 }
860
861 if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), NULL))) {
862 goto error;
863 }
864
867 if (!cfg->clients) {
868 goto error;
869 }
870
871 return cfg;
872error:
873 ao2_ref(cfg, -1);
874 return NULL;
875}
#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:837
static int xmpp_config_cmp(void *obj, void *arg, int flags)
Comparator function for configuration.
Definition: res_xmpp.c:845
struct ao2_container * clients
Definition: res_xmpp.c:604
struct ast_xmpp_global_config * global
Definition: res_xmpp.c:603

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 845 of file res_xmpp.c.

846{
847 struct ast_xmpp_client_config *one = obj, *two = arg;
848 const char *match = (flags & OBJ_KEY) ? arg : two->name;
849 return strcasecmp(one->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
850}
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:2388

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 837 of file res_xmpp.c.

838{
839 struct xmpp_config *cfg = obj;
840 ao2_cleanup(cfg->global);
841 ao2_cleanup(cfg->clients);
842}

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 922 of file res_xmpp.c.

923{
925
927}
static int xmpp_client_config_post_apply(void *obj, void *arg, int flags)
Definition: res_xmpp.c:3992

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

◆ xmpp_config_prelink()

static int xmpp_config_prelink ( void *  newitem)
static

Definition at line 877 of file res_xmpp.c.

878{
879 struct ast_xmpp_client_config *clientcfg = newitem;
881 RAII_VAR(struct ast_xmpp_client_config *, oldclientcfg, NULL, ao2_cleanup);
882
883 if (ast_strlen_zero(clientcfg->user)) {
884 ast_log(LOG_ERROR, "No user specified on client '%s'\n", clientcfg->name);
885 return -1;
886 } else if (ast_strlen_zero(clientcfg->password) && ast_strlen_zero(clientcfg->refresh_token)) {
887 ast_log(LOG_ERROR, "No password or refresh_token specified on client '%s'\n", clientcfg->name);
888 return -1;
889 } else if (ast_strlen_zero(clientcfg->server)) {
890 ast_log(LOG_ERROR, "No server specified on client '%s'\n", clientcfg->name);
891 return -1;
892 } else if (!ast_strlen_zero(clientcfg->refresh_token) &&
893 (ast_strlen_zero(clientcfg->oauth_clientid) || ast_strlen_zero(clientcfg->oauth_secret))) {
894 ast_log(LOG_ERROR, "No oauth_clientid or oauth_secret specified, so client '%s' can't be used\n", clientcfg->name);
895 return -1;
896 }
897
898 /* If this is a new connection force a reconnect */
899 if (!cfg || !cfg->clients || !(oldclientcfg = xmpp_config_find(cfg->clients, clientcfg->name))) {
900 clientcfg->client->reconnect = 1;
901 return 0;
902 }
903
904 /* If any configuration options are changing that would require reconnecting set the bit so we will do so if possible */
905 if (strcmp(clientcfg->user, oldclientcfg->user) ||
906 strcmp(clientcfg->password, oldclientcfg->password) ||
907 strcmp(clientcfg->refresh_token, oldclientcfg->refresh_token) ||
908 strcmp(clientcfg->oauth_clientid, oldclientcfg->oauth_clientid) ||
909 strcmp(clientcfg->oauth_secret, oldclientcfg->oauth_secret) ||
910 strcmp(clientcfg->server, oldclientcfg->server) ||
911 (clientcfg->port != oldclientcfg->port) ||
912 (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT) != ast_test_flag(&oldclientcfg->flags, XMPP_COMPONENT)) ||
913 (clientcfg->priority != oldclientcfg->priority)) {
914 clientcfg->client->reconnect = 1;
915 } else {
916 clientcfg->client->reconnect = 0;
917 }
918
919 return 0;
920}
const ast_string_field server
Definition: res_xmpp.c:591

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 2562 of file res_xmpp.c.

2563{
2565 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2566 struct ast_xmpp_client *client = data;
2567 iks *roster;
2568
2569 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
2570 return -1;
2571 }
2572
2573 client->jid = (iks_find_cdata(pak->query, "jid")) ? iks_id_new(client->stack, iks_find_cdata(pak->query, "jid")) : client->jid;
2574
2575 if (ast_test_flag(&clientcfg->flags, XMPP_DISTRIBUTE_EVENTS)) {
2577 }
2578
2579 if (!(roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER))) {
2580 ast_log(LOG_ERROR, "Unable to allocate memory for roster request for client '%s'\n", client->name);
2581 return -1;
2582 }
2583
2584 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);
2585 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);
2586
2587 iks_insert_attrib(roster, "id", "roster");
2588 ast_xmpp_client_send(client, roster);
2589
2590 iks_filter_remove_hook(client->filter, xmpp_connect_hook);
2591 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);
2592
2593 xmpp_client_set_presence(client, NULL, client->jid->full, clientcfg->status, clientcfg->statusmsg);
2595
2596 return IKS_FILTER_EAT;
2597}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
static int xmpp_client_service_discovery_get_hook(void *data, ikspak *pak)
Hook function called when client receives a service discovery get message.
Definition: res_xmpp.c:2472
static int xmpp_roster_hook(void *data, ikspak *pak)
Hook function called when roster is received from server.
Definition: res_xmpp.c:2376
static void xmpp_init_event_distribution(struct ast_xmpp_client *client)
Initialize collections for event distribution.
Definition: res_xmpp.c:1712
@ XMPP_STATE_ROSTER
Definition: xmpp.h:79

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

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

◆ xmpp_do_set_debug()

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

Definition at line 4429 of file res_xmpp.c.

4430{
4431 switch (cmd) {
4432 case CLI_INIT:
4433 e->command = "xmpp set debug {on|off}";
4434 e->usage =
4435 "Usage: xmpp set debug {on|off}\n"
4436 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n";
4437 return NULL;
4438 case CLI_GENERATE:
4439 return NULL;
4440 }
4441
4442 if (a->argc != e->args) {
4443 return CLI_SHOWUSAGE;
4444 }
4445
4446 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
4447 debug = 1;
4448 ast_cli(a->fd, "XMPP Debugging Enabled.\n");
4449 return CLI_SUCCESS;
4450 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
4451 debug = 0;
4452 ast_cli(a->fd, "XMPP Debugging Disabled.\n");
4453 return CLI_SUCCESS;
4454 }
4455 return CLI_SHOWUSAGE; /* defaults to invalid */
4456}
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 1712 of file res_xmpp.c.

1713{
1715 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1716 RAII_VAR(struct ao2_container *, cached, NULL, ao2_cleanup);
1717
1718 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
1719 return;
1720 }
1721
1722 xmpp_pubsub_unsubscribe(client, "device_state");
1723 xmpp_pubsub_unsubscribe(client, "message_waiting");
1724
1726 return;
1727 }
1730
1732 client->mwi_sub = stasis_unsubscribe(client->mwi_sub);
1733 return;
1734 }
1737
1739 ao2_callback(cached, OBJ_NODATA, cached_devstate_cb, client);
1740
1741 xmpp_pubsub_subscribe(client, "device_state");
1742 xmpp_pubsub_subscribe(client, "message_waiting");
1743 iks_filter_add_rule(client->filter, xmpp_pubsub_handle_event, client, IKS_RULE_TYPE,
1744 IKS_PAK_MESSAGE, IKS_RULE_FROM, clientcfg->pubsubnode, IKS_RULE_DONE);
1745 iks_filter_add_rule(client->filter, xmpp_pubsub_handle_error, client, IKS_RULE_TYPE,
1746 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE);
1747
1748}
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:676
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:671
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
struct stasis_topic * ast_mwi_topic_all(void)
Get the Stasis Message Bus API topic for MWI messages.
Definition: mwi.c:89
static void xmpp_pubsub_subscribe(struct ast_xmpp_client *client, const char *node)
Subscribe to a PubSub node.
Definition: res_xmpp.c:1539
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:1464
static int cached_devstate_cb(void *obj, void *arg, int flags)
Definition: res_xmpp.c:1700
static int xmpp_pubsub_handle_error(void *data, ikspak *pak)
Definition: res_xmpp.c:1632
static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
Callback for handling PubSub events.
Definition: res_xmpp.c:1586
struct ao2_container * stasis_cache_dump(struct stasis_cache *cache, struct stasis_message_type *type)
Dump cached items to a subscription for the ast_eid_default entity.
Definition: stasis_cache.c:736
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1050
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:1104
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:680
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:998
#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 3743 of file res_xmpp.c.

3744{
3745 struct pollfd pfd = { .events = POLLIN };
3746 int len, res;
3747
3748#ifdef HAVE_OPENSSL
3749 if (xmpp_is_secure(client)) {
3750 pfd.fd = SSL_get_fd(client->ssl_session);
3751 if (pfd.fd < 0) {
3752 return -1;
3753 }
3754 } else
3755#endif /* HAVE_OPENSSL */
3756 pfd.fd = iks_fd(client->parser);
3757
3758 res = ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
3759 if (res > 0) {
3760#ifdef HAVE_OPENSSL
3761 if (xmpp_is_secure(client)) {
3762 len = SSL_read(client->ssl_session, buffer, buf_len);
3763 } else
3764#endif /* HAVE_OPENSSL */
3765 len = recv(pfd.fd, buffer, buf_len, 0);
3766
3767 if (len > 0) {
3768 return len;
3769 } else if (len <= 0) {
3770 return -1;
3771 }
3772 }
3773 return res;
3774}
#define ast_poll(a, b, c)
Definition: poll-compat.h:88

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

Referenced by xmpp_client_receive().

◆ xmpp_is_secure()

static int xmpp_is_secure ( struct ast_xmpp_client client)
static

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

Definition at line 1001 of file res_xmpp.c.

1002{
1003#ifdef HAVE_OPENSSL
1004 return client->stream_flags & SECURE;
1005#else
1006 return 0;
1007#endif
1008}

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

◆ xmpp_join_exec()

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

Application to join a chat room.

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

Definition at line 1847 of file res_xmpp.c.

1848{
1850 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1851 char *s, nick[XMPP_MAX_RESJIDLEN];
1853 AST_APP_ARG(sender);
1854 AST_APP_ARG(jid);
1855 AST_APP_ARG(nick);
1856 );
1857
1858 if (ast_strlen_zero(data)) {
1859 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
1860 return -1;
1861 }
1862 s = ast_strdupa(data);
1863
1865 if (args.argc < 2 || args.argc > 3) {
1866 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
1867 return -1;
1868 }
1869
1870 if (strchr(args.jid, '/')) {
1871 ast_log(LOG_ERROR, "Invalid room name : resource must not be appended\n");
1872 return -1;
1873 }
1874
1875 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1876 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
1877 return -1;
1878 }
1879
1880 if (ast_strlen_zero(args.nick)) {
1881 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1882 snprintf(nick, sizeof(nick), "asterisk");
1883 } else {
1884 snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
1885 }
1886 } else {
1887 snprintf(nick, sizeof(nick), "%s", args.nick);
1888 }
1889
1890 if (!ast_strlen_zero(args.jid) && strchr(args.jid, '@')) {
1891 ast_xmpp_chatroom_join(clientcfg->client, args.jid, nick);
1892 } else {
1893 ast_log(LOG_ERROR, "Problem with specified jid of '%s'\n", args.jid);
1894 }
1895
1896 return 0;
1897}
int ast_xmpp_chatroom_join(struct ast_xmpp_client *client, const char *room, const char *nickname)
Join an XMPP multi-user chatroom.
Definition: res_xmpp.c:1139
#define XMPP_MAX_RESJIDLEN
Maximum size of a resource JID.
Definition: xmpp.h:65

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

Referenced by load_module().

◆ xmpp_leave_exec()

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

Application to leave a chat room.

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

Definition at line 1906 of file res_xmpp.c.

1907{
1909 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1910 char *s, nick[XMPP_MAX_RESJIDLEN];
1912 AST_APP_ARG(sender);
1913 AST_APP_ARG(jid);
1914 AST_APP_ARG(nick);
1915 );
1916
1917 if (ast_strlen_zero(data)) {
1918 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
1919 return -1;
1920 }
1921 s = ast_strdupa(data);
1922
1924 if (args.argc < 2 || args.argc > 3) {
1925 ast_log(LOG_ERROR, "%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
1926 return -1;
1927 }
1928
1929 if (strchr(args.jid, '/')) {
1930 ast_log(LOG_ERROR, "Invalid room name, resource must not be appended\n");
1931 return -1;
1932 }
1933
1934 if (ast_strlen_zero(args.jid) || !strchr(args.jid, '@')) {
1935 ast_log(LOG_ERROR, "No jabber ID specified\n");
1936 return -1;
1937 }
1938
1939 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1940 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
1941 return -1;
1942 }
1943
1944 if (ast_strlen_zero(args.nick)) {
1945 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
1946 snprintf(nick, sizeof(nick), "asterisk");
1947 } else {
1948 snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
1949 }
1950 } else {
1951 snprintf(nick, sizeof(nick), "%s", args.nick);
1952 }
1953
1954 ast_xmpp_chatroom_leave(clientcfg->client, args.jid, nick);
1955
1956 return 0;
1957}
int ast_xmpp_chatroom_leave(struct ast_xmpp_client *client, const char *room, const char *nickname)
Leave an XMPP multi-user chatroom.
Definition: res_xmpp.c:1149

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

Referenced by load_module().

◆ xmpp_log_hook()

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

Logging hook function.

Definition at line 2600 of file res_xmpp.c.

2601{
2603 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2604 struct ast_xmpp_client *client = data;
2605
2606 if (!debug && (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) || !ast_test_flag(&clientcfg->flags, XMPP_DEBUG))) {
2607 return;
2608 }
2609
2610 if (!incoming) {
2611 ast_verbose("\n<--- XMPP sent to '%s' --->\n%s\n<------------->\n", client->name, xmpp);
2612 } else {
2613 ast_verbose("\n<--- XMPP received from '%s' --->\n%s\n<------------->\n", client->name, xmpp);
2614 }
2615}
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206

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

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

◆ xmpp_message_destroy()

static void xmpp_message_destroy ( struct ast_xmpp_message message)
static

Destroy function for XMPP messages.

Definition at line 667 of file res_xmpp.c.

668{
669 if (message->from) {
670 ast_free(message->from);
671 }
672 if (message->message) {
673 ast_free(message->message);
674 }
675
677}

References ast_free.

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

◆ xmpp_pak_message()

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

Internal function called when a message is received.

Definition at line 3246 of file res_xmpp.c.

3247{
3248 struct ast_xmpp_message *message;
3249 char *body;
3250 int deleted = 0;
3251
3252 ast_debug(3, "XMPP client '%s' received a message\n", client->name);
3253
3254 if (!(body = iks_find_cdata(pak->x, "body"))) {
3255 /* Message contains no body, ignore it. */
3256 return 0;
3257 }
3258
3259 if (!(message = ast_calloc(1, sizeof(*message)))) {
3260 return -1;
3261 }
3262
3263 message->arrived = ast_tvnow();
3264
3265 message->message = ast_strdup(body);
3266
3267 ast_copy_string(message->id, S_OR(pak->id, ""), sizeof(message->id));
3268 message->from = !ast_strlen_zero(pak->from->full) ? ast_strdup(pak->from->full) : NULL;
3269
3271 struct ast_msg *msg;
3272 struct ast_xmpp_buddy *buddy;
3273
3274 if ((msg = ast_msg_alloc())) {
3275 int res;
3276
3277 ast_xmpp_client_lock(client);
3278
3279 buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY | OBJ_NOLOCK);
3280
3281 res = ast_msg_set_to(msg, "xmpp:%s", cfg->user);
3282 res |= ast_msg_set_from(msg, "xmpp:%s", message->from);
3283 res |= ast_msg_set_body(msg, "%s", message->message);
3284 res |= ast_msg_set_context(msg, "%s", cfg->context);
3285 res |= ast_msg_set_tech(msg, "%s", "XMPP");
3286 res |= ast_msg_set_endpoint(msg, "%s", client->name);
3287
3288 if (buddy) {
3289 res |= ast_msg_set_var(msg, "XMPP_BUDDY", buddy->id);
3290 }
3291
3292 ao2_cleanup(buddy);
3293
3294 ast_xmpp_client_unlock(client);
3295
3296 if (res) {
3297 ast_msg_destroy(msg);
3298 } else {
3299 ast_msg_queue(msg);
3300 }
3301 }
3302 }
3303
3304 /* remove old messages received from this JID
3305 * and insert received message */
3306 deleted = delete_old_messages(client, pak->from->partial);
3307 ast_debug(3, "Deleted %d messages for client %s from JID %s\n", deleted, client->name, pak->from->partial);
3308 AST_LIST_LOCK(&client->messages);
3309 AST_LIST_INSERT_HEAD(&client->messages, message, list);
3310 AST_LIST_UNLOCK(&client->messages);
3311
3312 /* wake up threads waiting for messages */
3316
3317 return 0;
3318}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define ast_cond_broadcast(cond)
Definition: lock.h:211
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
Definition: main/message.c:491
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: main/message.c:474
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
Definition: main/message.c:546
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: main/message.c:535
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: main/message.c:444
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message going to the dialplan.
Definition: main/message.c:641
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: main/message.c:513
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
Definition: main/message.c:502
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
Definition: main/message.c:480
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: main/message.c:984
static int delete_old_messages(struct ast_xmpp_client *client, char *from)
Definition: res_xmpp.c:2221
A message.
Definition: main/message.c:259
const ast_string_field context
Definition: res_xmpp.c:591

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

◆ xmpp_pak_presence()

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

Internal function called when a presence message is received.

Definition at line 3392 of file res_xmpp.c.

3393{
3394 struct ast_xmpp_buddy *buddy;
3396 char *type = iks_find_attrib(pak->x, "type");
3397 int status = pak->show ? pak->show : STATUS_DISAPPEAR;
3399
3400 /* If this is a component presence probe request answer immediately with our presence status */
3401 if (ast_test_flag(&cfg->flags, XMPP_COMPONENT) && !ast_strlen_zero(type) && !strcasecmp(type, "probe")) {
3402 xmpp_client_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), cfg->status, cfg->statusmsg);
3403 }
3404
3405 /* If no resource is available this is a general buddy presence update, which we will ignore */
3406 if (!pak->from->resource) {
3407 return 0;
3408 }
3409
3410 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY))) {
3411 /* Only output the message if it is not about us */
3412 if (strcmp(client->jid->partial, pak->from->partial)) {
3413 ast_log(LOG_WARNING, "Received presence information about '%s' despite not having them in roster on client '%s'\n",
3414 pak->from->partial, client->name);
3415 }
3416 return 0;
3417 }
3418
3419 ao2_lock(buddy->resources);
3420
3421 if (!(resource = ao2_callback(buddy->resources, OBJ_NOLOCK, xmpp_resource_cmp, pak->from->resource))) {
3422 /* Only create the new resource if it is not going away - in reality this should not happen */
3423 if (status != STATUS_DISAPPEAR) {
3425 ast_log(LOG_ERROR, "Could not allocate resource object for resource '%s' of buddy '%s' on client '%s'\n",
3426 pak->from->resource, buddy->id, client->name);
3427 ao2_unlock(buddy->resources);
3428 ao2_ref(buddy, -1);
3429 return 0;
3430 }
3431
3432 ast_copy_string(resource->resource, pak->from->resource, sizeof(resource->resource));
3433 }
3434 } else {
3435 /* We unlink the resource in case the priority changes or in case they are going away */
3437 }
3438
3439 /* Only update the resource and add it back in if it is not going away */
3440 if (resource && (status != STATUS_DISAPPEAR)) {
3441 char *node, *ver;
3442
3443 /* Try to get the XMPP spec node, and fall back to Google if not found */
3444 if (!(node = iks_find_attrib(iks_find(pak->x, "c"), "node"))) {
3445 node = iks_find_attrib(iks_find(pak->x, "caps:c"), "node");
3446 }
3447
3448 if (!(ver = iks_find_attrib(iks_find(pak->x, "c"), "ver"))) {
3449 ver = iks_find_attrib(iks_find(pak->x, "caps:c"), "ver");
3450 }
3451
3452 if (resource->description) {
3453 ast_free(resource->description);
3454 }
3455
3456 if ((node && strcmp(resource->caps.node, node)) || (ver && strcmp(resource->caps.version, ver))) {
3457 /* For interoperability reasons, proceed even if the resource fails to provide node or version */
3458 if (node) {
3459 ast_copy_string(resource->caps.node, node, sizeof(resource->caps.node));
3460 }
3461 if (ver) {
3462 ast_copy_string(resource->caps.version, ver, sizeof(resource->caps.version));
3463 }
3464
3465 /* Google Talk places the capabilities information directly in presence, so see if it is there */
3466 if (iks_find_with_attrib(pak->x, "c", "node", "http://www.google.com/xmpp/client/caps") ||
3467 iks_find_with_attrib(pak->x, "caps:c", "node", "http://www.google.com/xmpp/client/caps") ||
3468 iks_find_with_attrib(pak->x, "c", "node", "http://www.android.com/gtalk/client/caps") ||
3469 iks_find_with_attrib(pak->x, "caps:c", "node", "http://www.android.com/gtalk/client/caps") ||
3470 iks_find_with_attrib(pak->x, "c", "node", "http://mail.google.com/xmpp/client/caps") ||
3471 iks_find_with_attrib(pak->x, "caps:c", "node", "http://mail.google.com/xmpp/client/caps")) {
3472 resource->caps.google = 1;
3473 }
3474
3475 /* To discover if the buddy supports Jingle we need to query, so do so */
3476 if (xmpp_client_send_disco_info_request(client, pak->from->full, client->jid->full)) {
3477 ast_log(LOG_WARNING, "Could not send discovery information request to resource '%s' of buddy '%s' on client '%s', capabilities may be incomplete\n", resource->resource, buddy->id, client->name);
3478 }
3479 }
3480
3481 resource->status = status;
3482 resource->description = ast_strdup(iks_find_cdata(pak->x, "status"));
3483 resource->priority = atoi((iks_find_cdata(pak->x, "priority")) ? iks_find_cdata(pak->x, "priority") : "0");
3484
3486
3487 manager_event(EVENT_FLAG_USER, "JabberStatus",
3488 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d"
3489 "\r\nDescription: %s\r\n",
3490 client->name, pak->from->partial, resource->resource, resource->status,
3491 resource->priority, S_OR(resource->description, ""));
3492
3493 ao2_ref(resource, -1);
3494 } else {
3495 /* This will get hit by presence coming in for an unknown resource, and also when a resource goes away */
3496 if (resource) {
3497 ao2_ref(resource, -1);
3498 }
3499
3500 manager_event(EVENT_FLAG_USER, "JabberStatus",
3501 "Account: %s\r\nJID: %s\r\nStatus: %u\r\n",
3502 client->name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE);
3503 }
3504
3505 /* Determine if at least one resource is available for device state purposes */
3508 ao2_ref(resource, -1);
3509 }
3510
3511 ao2_unlock(buddy->resources);
3512
3513 ao2_ref(buddy, -1);
3514
3515 ast_devstate_changed(state, AST_DEVSTATE_CACHABLE, "XMPP/%s/%s", client->name, pak->from->partial);
3516
3517 return 0;
3518}
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:513
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:254
#define EVENT_FLAG_USER
Definition: manager.h:81
static int xmpp_resource_is_available(void *obj, void *arg, int flags)
Callback function which returns when the resource is available.
Definition: res_xmpp.c:3350
#define STATUS_DISAPPEAR
Status for a disappearing buddy.
Definition: res_xmpp.c:567
static void xmpp_resource_destructor(void *obj)
Destructor callback function for XMPP resource.
Definition: res_xmpp.c:964
static int xmpp_client_send_disco_info_request(struct ast_xmpp_client *client, const char *to, const char *from)
Helper function which sends a discovery information request to a user.
Definition: res_xmpp.c:3321

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

◆ xmpp_pak_s10n()

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

Internal function called when a subscription message is received.

Definition at line 3521 of file res_xmpp.c.

3522{
3523 struct ast_xmpp_buddy *buddy;
3524
3525 switch (pak->subtype) {
3526 case IKS_TYPE_SUBSCRIBE:
3528 iks *presence, *status = NULL;
3529
3530 if ((presence = iks_new("presence")) && (status = iks_new("status"))) {
3531 iks_insert_attrib(presence, "type", "subscribed");
3532 iks_insert_attrib(presence, "to", pak->from->full);
3533 iks_insert_attrib(presence, "from", client->jid->full);
3534
3535 if (pak->id) {
3536 iks_insert_attrib(presence, "id", pak->id);
3537 }
3538
3539 iks_insert_cdata(status, "Asterisk has approved your subscription", 0);
3540 iks_insert_node(presence, status);
3541
3542 if (ast_xmpp_client_send(client, presence)) {
3543 ast_log(LOG_ERROR, "Could not send subscription acceptance to '%s' from client '%s'\n",
3544 pak->from->partial, client->name);
3545 }
3546 } else {
3547 ast_log(LOG_ERROR, "Could not allocate presence stanzas for accepting subscription from '%s' to client '%s'\n",
3548 pak->from->partial, client->name);
3549 }
3550
3551 iks_delete(status);
3552 iks_delete(presence);
3553 }
3554
3555 if (ast_test_flag(&cfg->flags, XMPP_COMPONENT)) {
3556 xmpp_client_set_presence(client, pak->from->full, iks_find_attrib(pak->x, "to"), cfg->status, cfg->statusmsg);
3557 }
3558 /* This purposely flows through so we have the subscriber amongst our buddies */
3559 case IKS_TYPE_SUBSCRIBED:
3560 ao2_lock(client->buddies);
3561
3562 if (!(buddy = ao2_find(client->buddies, pak->from->partial, OBJ_KEY | OBJ_NOLOCK))) {
3563 buddy = xmpp_client_create_buddy(client->buddies, pak->from->partial);
3564 }
3565
3566 if (!buddy) {
3567 ast_log(LOG_WARNING, "Could not find or create buddy '%s' on client '%s'\n",
3568 pak->from->partial, client->name);
3569 } else {
3570 ao2_ref(buddy, -1);
3571 }
3572
3573 ao2_unlock(client->buddies);
3574
3575 break;
3576 default:
3577 break;
3578 }
3579
3580 return 0;
3581}

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

◆ xmpp_ping_request()

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

Helper function which sends a ping request to a server.

Definition at line 3358 of file res_xmpp.c.

3359{
3360 iks *iq, *ping;
3361 int res;
3362
3363 ast_debug(2, "JABBER: Sending Keep-Alive Ping for client '%s'\n", client->name);
3364
3365 if (!(iq = iks_new("iq")) || !(ping = iks_new("ping"))) {
3366 iks_delete(iq);
3367 return -1;
3368 }
3369
3370 iks_insert_attrib(iq, "type", "get");
3371 iks_insert_attrib(iq, "to", to);
3372 iks_insert_attrib(iq, "from", from);
3373
3374 ast_xmpp_client_lock(client);
3375 iks_insert_attrib(iq, "id", client->mid);
3376 ast_xmpp_increment_mid(client->mid);
3377 ast_xmpp_client_unlock(client);
3378
3379 iks_insert_attrib(ping, "xmlns", "urn:xmpp:ping");
3380 iks_insert_node(iq, ping);
3381
3382 res = ast_xmpp_client_send(client, iq);
3383
3384 iks_delete(ping);
3385 iks_delete(iq);
3386
3387
3388 return res;
3389}

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

Referenced by xmpp_client_receive(), and xmpp_client_thread().

◆ xmpp_pubsub_build_node_config()

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

Definition at line 1243 of file res_xmpp.c.

1244{
1245 iks *configure, *x, *field_owner, *field_node_type, *field_node_config,
1246 *field_deliver_payload, *field_persist_items, *field_access_model,
1247 *field_pubsub_collection;
1248 configure = iks_insert(pubsub, "configure");
1249 x = iks_insert(configure, "x");
1250 iks_insert_attrib(x, "xmlns", "jabber:x:data");
1251 iks_insert_attrib(x, "type", "submit");
1252 field_owner = iks_insert(x, "field");
1253 iks_insert_attrib(field_owner, "var", "FORM_TYPE");
1254 iks_insert_attrib(field_owner, "type", "hidden");
1255 iks_insert_cdata(iks_insert(field_owner, "value"),
1256 "http://jabber.org/protocol/pubsub#owner", 39);
1257 if (node_type) {
1258 field_node_type = iks_insert(x, "field");
1259 iks_insert_attrib(field_node_type, "var", "pubsub#node_type");
1260 iks_insert_cdata(iks_insert(field_node_type, "value"), node_type, strlen(node_type));
1261 }
1262 field_node_config = iks_insert(x, "field");
1263 iks_insert_attrib(field_node_config, "var", "FORM_TYPE");
1264 iks_insert_attrib(field_node_config, "type", "hidden");
1265 iks_insert_cdata(iks_insert(field_node_config, "value"),
1266 "http://jabber.org/protocol/pubsub#node_config", 45);
1267 field_deliver_payload = iks_insert(x, "field");
1268 iks_insert_attrib(field_deliver_payload, "var", "pubsub#deliver_payloads");
1269 iks_insert_cdata(iks_insert(field_deliver_payload, "value"), "1", 1);
1270 field_persist_items = iks_insert(x, "field");
1271 iks_insert_attrib(field_persist_items, "var", "pubsub#persist_items");
1272 iks_insert_cdata(iks_insert(field_persist_items, "value"), "1", 1);
1273 field_access_model = iks_insert(x, "field");
1274 iks_insert_attrib(field_access_model, "var", "pubsub#access_model");
1275 iks_insert_cdata(iks_insert(field_access_model, "value"), "whitelist", 9);
1276 if (node_type && !strcasecmp(node_type, "leaf")) {
1277 field_pubsub_collection = iks_insert(x, "field");
1278 iks_insert_attrib(field_pubsub_collection, "var", "pubsub#collection");
1279 iks_insert_cdata(iks_insert(field_pubsub_collection, "value"), collection_name,
1280 strlen(collection_name));
1281 }
1282 return configure;
1283}
node_type
Definition: ast_expr2.c:333

Referenced by xmpp_pubsub_create_node().

◆ xmpp_pubsub_build_node_request()

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

Build the a node request.

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

Definition at line 4103 of file res_xmpp.c.

4104{
4105 iks *request = xmpp_pubsub_iq_create(client, "get"), *query;
4106
4107 if (!request) {
4108 return NULL;
4109 }
4110
4111 query = iks_insert(request, "query");
4112 iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#items");
4113
4114 if (collection) {
4115 iks_insert_attrib(query, "node", collection);
4116 }
4117
4118 return request;
4119}
static int request(void *obj)
Definition: chan_pjsip.c:2605
static iks * xmpp_pubsub_iq_create(struct ast_xmpp_client *client, const char *type)
Create an IQ packet.
Definition: res_xmpp.c:1174

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

Referenced by xmpp_pubsub_purge_nodes(), and xmpp_pubsub_request_nodes().

◆ xmpp_pubsub_build_publish_skeleton()

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

Build the skeleton of a publish.

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

Definition at line 1206 of file res_xmpp.c.

1208{
1210 iks *request, *pubsub, *publish, *item;
1211
1212 if (!cfg || !cfg->global || !(request = xmpp_pubsub_iq_create(client, "set"))) {
1213 return NULL;
1214 }
1215
1216 pubsub = iks_insert(request, "pubsub");
1217 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1218 publish = iks_insert(pubsub, "publish");
1219 iks_insert_attrib(publish, "node", ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248) ? node : event_type);
1220 item = iks_insert(publish, "item");
1221 iks_insert_attrib(item, "id", node);
1222
1223 if (cachable == AST_DEVSTATE_NOT_CACHABLE) {
1224 iks *options, *x, *field_form_type, *field_persist;
1225
1226 options = iks_insert(pubsub, "publish-options");
1227 x = iks_insert(options, "x");
1228 iks_insert_attrib(x, "xmlns", "jabber:x:data");
1229 iks_insert_attrib(x, "type", "submit");
1230 field_form_type = iks_insert(x, "field");
1231 iks_insert_attrib(field_form_type, "var", "FORM_TYPE");
1232 iks_insert_attrib(field_form_type, "type", "hidden");
1233 iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0);
1234 field_persist = iks_insert(x, "field");
1235 iks_insert_attrib(field_persist, "var", "pubsub#persist_items");
1236 iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1);
1237 }
1238
1239 return item;
1240
1241}
@ AST_DEVSTATE_NOT_CACHABLE
Definition: devicestate.h:69
unsigned char publish
Definition: res_corosync.c:241
static struct test_options options

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

Referenced by xmpp_pubsub_publish_device_state(), and xmpp_pubsub_publish_mwi().

◆ xmpp_pubsub_create_affiliations()

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

Add Owner affiliations for pubsub node.

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

Definition at line 1290 of file res_xmpp.c.

1291{
1292 iks *modify_affiliates = xmpp_pubsub_iq_create(client, "set");
1293 iks *pubsub, *affiliations, *affiliate;
1294 struct ao2_iterator i;
1295 struct ast_xmpp_buddy *buddy;
1296
1297 if (!modify_affiliates) {
1298 ast_log(LOG_ERROR, "Could not create IQ for creating affiliations on client '%s'\n", client->name);
1299 return;
1300 }
1301
1302 pubsub = iks_insert(modify_affiliates, "pubsub");
1303 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner");
1304 affiliations = iks_insert(pubsub, "affiliations");
1305 iks_insert_attrib(affiliations, "node", node);
1306
1307 i = ao2_iterator_init(client->buddies, 0);
1308 while ((buddy = ao2_iterator_next(&i))) {
1309 affiliate = iks_insert(affiliations, "affiliation");
1310 iks_insert_attrib(affiliate, "jid", buddy->id);
1311 iks_insert_attrib(affiliate, "affiliation", "owner");
1312 ao2_ref(buddy, -1);
1313 }
1315
1316 ast_xmpp_client_send(client, modify_affiliates);
1317 iks_delete(modify_affiliates);
1318}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

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

Referenced by xmpp_pubsub_create_node().

◆ xmpp_pubsub_create_collection()

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

Create a PubSub collection node.

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

Definition at line 1373 of file res_xmpp.c.

1374{
1375 xmpp_pubsub_create_node(client, "collection", collection_name, NULL);
1376}
static void xmpp_pubsub_create_node(struct ast_xmpp_client *client, const char *node_type, const char *name, const char *collection_name)
Create a pubsub node.
Definition: res_xmpp.c:1327

References NULL, and xmpp_pubsub_create_node().

Referenced by xmpp_cli_create_collection(), and xmpp_pubsub_handle_error().

◆ xmpp_pubsub_create_leaf()

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

Create a PubSub leaf node.

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

Definition at line 1385 of file res_xmpp.c.

1387{
1388 xmpp_pubsub_create_node(client, "leaf", leaf_name, collection_name);
1389}

References xmpp_pubsub_create_node().

Referenced by xmpp_cli_create_leafnode(), and xmpp_pubsub_handle_error().

◆ xmpp_pubsub_create_node()

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

Create a pubsub node.

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

Definition at line 1327 of file res_xmpp.c.

1329{
1330 iks *node, *pubsub, *create;
1331
1332 if (!(node = xmpp_pubsub_iq_create(client, "set"))) {
1333 return;
1334 }
1335
1336 pubsub = iks_insert(node, "pubsub");
1337 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1338 create = iks_insert(pubsub, "create");
1339 iks_insert_attrib(create, "node", name);
1340 xmpp_pubsub_build_node_config(pubsub, node_type, collection_name);
1341 ast_xmpp_client_send(client, node);
1343 iks_delete(node);
1344}
static iks * xmpp_pubsub_build_node_config(iks *pubsub, const char *node_type, const char *collection_name)
Definition: res_xmpp.c:1243
static void xmpp_pubsub_create_affiliations(struct ast_xmpp_client *client, const char *node)
Add Owner affiliations for pubsub node.
Definition: res_xmpp.c:1290

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

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

◆ xmpp_pubsub_delete_node()

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

Delete a PubSub node.

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

Definition at line 1351 of file res_xmpp.c.

1352{
1353 iks *request, *pubsub, *delete;
1354
1355 if (!(request = xmpp_pubsub_iq_create(client, "set"))) {
1356 return;
1357 }
1358
1359 pubsub = iks_insert(request, "pubsub");
1360 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub#owner");
1361 delete = iks_insert(pubsub, "delete");
1362 iks_insert_attrib(delete, "node", node_name);
1364
1365 iks_delete(request);
1366}

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

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

◆ xmpp_pubsub_delete_node_list()

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

Delete pubsub item lists.

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

Definition at line 4225 of file res_xmpp.c.

4226{
4227 struct ast_xmpp_client *client = data;
4228 iks *item = NULL;
4229
4230 if (iks_has_children(pak->query)) {
4231 item = iks_first_tag(pak->query);
4232 ast_log(LOG_WARNING, "Connection: %s Node name: %s\n", client->jid->partial,
4233 iks_find_attrib(item, "node"));
4234 while ((item = iks_next_tag(item))) {
4235 xmpp_pubsub_delete_node(client, iks_find_attrib(item, "node"));
4236 }
4237 }
4238
4239 if (item) {
4240 iks_delete(item);
4241 }
4242
4243 return IKS_FILTER_EAT;
4244}

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

Referenced by xmpp_pubsub_purge_nodes().

◆ xmpp_pubsub_devstate_cb()

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

Callback function for device state events.

Parameters
datavoid pointer to ast_client structure
sub,msg

Definition at line 1491 of file res_xmpp.c.

1492{
1493 struct ast_xmpp_client *client = data;
1494 struct ast_device_state_message *dev_state;
1495
1497 return;
1498 }
1499
1500 dev_state = stasis_message_data(msg);
1501 if (!dev_state->eid || ast_eid_cmp(&ast_eid_default, dev_state->eid)) {
1502 /* If the event is aggregate or didn't originate from this server, don't send it out. */
1503 return;
1504 }
1505
1506 xmpp_pubsub_publish_device_state(client, dev_state->device, ast_devstate_str(dev_state->state), dev_state->cachable);
1507}
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:258
struct stasis_forward * sub
Definition: res_corosync.c:240
static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, const char *device, const char *device_state, unsigned int cachable)
Publish device state to a PubSub node.
Definition: res_xmpp.c:1429
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int stasis_subscription_is_subscribed(const struct stasis_subscription *sub)
Returns whether a subscription is currently subscribed.
Definition: stasis.c:1177
The structure that contains device state.
Definition: devicestate.h:238
enum ast_device_state state
Definition: devicestate.h:248
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246
enum ast_devstate_cache cachable
Definition: devicestate.h:250
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition: utils.c:3094

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

Referenced by cached_devstate_cb(), and xmpp_init_event_distribution().

◆ xmpp_pubsub_handle_error()

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

Definition at line 1632 of file res_xmpp.c.

1633{
1635 char *node_name, *error;
1636 int error_num;
1637 iks *orig_request, *orig_pubsub = iks_find(pak->x, "pubsub");
1638 struct ast_xmpp_client *client = data;
1639
1640 if (!cfg || !cfg->global) {
1641 ast_log(LOG_ERROR, "No global configuration available\n");
1642 return IKS_FILTER_EAT;
1643 }
1644
1645 if (!orig_pubsub) {
1646 ast_debug(1, "Error isn't a PubSub error, why are we here?\n");
1647 return IKS_FILTER_EAT;
1648 }
1649
1650 orig_request = iks_child(orig_pubsub);
1651 error = iks_find_attrib(iks_find(pak->x, "error"), "code");
1652 node_name = iks_find_attrib(orig_request, "node");
1653
1654 if (!sscanf(error, "%30d", &error_num)) {
1655 return IKS_FILTER_EAT;
1656 }
1657
1658 if (error_num > 399 && error_num < 500 && error_num != 404) {
1660 "Error performing operation on PubSub node %s, %s.\n", node_name, error);
1661 return IKS_FILTER_EAT;
1662 } else if (error_num > 499 && error_num < 600) {
1663 ast_log(LOG_ERROR, "PubSub Server error, %s\n", error);
1664 return IKS_FILTER_EAT;
1665 }
1666
1667 if (!strcasecmp(iks_name(orig_request), "publish")) {
1668 iks *request;
1669
1670 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1671 if (iks_find(iks_find(orig_request, "item"), "state")) {
1672 xmpp_pubsub_create_leaf(client, "device_state", node_name);
1673 } else if (iks_find(iks_find(orig_request, "item"), "mailbox")) {
1674 xmpp_pubsub_create_leaf(client, "message_waiting", node_name);
1675 }
1676 } else {
1677 xmpp_pubsub_create_node(client, NULL, node_name, NULL);
1678 }
1679
1680 if ((request = xmpp_pubsub_iq_create(client, "set"))) {
1681 iks_insert_node(request, orig_pubsub);
1683 iks_delete(request);
1684 } else {
1685 ast_log(LOG_ERROR, "PubSub publish could not create IQ\n");
1686 }
1687
1688 return IKS_FILTER_EAT;
1689 } else if (!strcasecmp(iks_name(orig_request), "subscribe")) {
1690 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1691 xmpp_pubsub_create_collection(client, node_name);
1692 } else {
1693 xmpp_pubsub_create_node(client, NULL, node_name, NULL);
1694 }
1695 }
1696
1697 return IKS_FILTER_EAT;
1698}

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

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_handle_event()

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

Callback for handling PubSub events.

Parameters
datavoid pointer to ast_xmpp_client structure
pakA pak
Return values
IKS_FILTER_EAT

Definition at line 1586 of file res_xmpp.c.

1587{
1588 char *item_id, *device_state, *mailbox, *cachable_str;
1589 int oldmsgs, newmsgs;
1590 iks *item, *item_content;
1591 struct ast_eid pubsub_eid;
1592 unsigned int cachable = AST_DEVSTATE_CACHABLE;
1593 item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item");
1594 if (!item) {
1595 ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n");
1596 return IKS_FILTER_EAT;
1597 }
1598 item_id = iks_find_attrib(item, "id");
1599 item_content = iks_child(item);
1600 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, "eid"));
1601 if (!ast_eid_cmp(&ast_eid_default, &pubsub_eid)) {
1602 ast_debug(1, "Returning here, eid of incoming event matches ours!\n");
1603 return IKS_FILTER_EAT;
1604 }
1605 if (!strcasecmp(iks_name(item_content), "state")) {
1606 if ((cachable_str = iks_find_attrib(item_content, "cachable"))) {
1607 sscanf(cachable_str, "%30u", &cachable);
1608 }
1609 device_state = iks_find_cdata(item, "state");
1611 ast_devstate_val(device_state),
1613 &pubsub_eid);
1614 return IKS_FILTER_EAT;
1615 } else if (!strcasecmp(iks_name(item_content), "mailbox")) {
1616 mailbox = strsep(&item_id, "@");
1617 sscanf(iks_find_cdata(item_content, "OLDMSGS"), "%10d", &oldmsgs);
1618 sscanf(iks_find_cdata(item_content, "NEWMSGS"), "%10d", &newmsgs);
1619
1620 ast_publish_mwi_state_full(mailbox, item_id, newmsgs, oldmsgs, NULL, &pubsub_eid);
1621
1622 return IKS_FILTER_EAT;
1623 } else {
1624 ast_debug(1, "Don't know how to handle PubSub event of type %s\n",
1625 iks_name(item_content));
1626 return IKS_FILTER_EAT;
1627 }
1628
1629 return IKS_FILTER_EAT;
1630}
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:263
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
Definition: devicestate.c:712
int ast_publish_mwi_state_full(const char *mailbox, const char *context, int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid)
Publish a MWI state update via stasis with all parameters.
Definition: mwi.c:393
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:813
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition: utils.c:3077

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

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_iq_create()

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

Create an IQ packet.

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

Definition at line 1174 of file res_xmpp.c.

1175{
1177 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1178 iks *request;
1179
1180 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name)) ||
1181 !(request = iks_new("iq"))) {
1182 return NULL;
1183 }
1184
1185 if (!ast_strlen_zero(clientcfg->pubsubnode)) {
1186 iks_insert_attrib(request, "to", clientcfg->pubsubnode);
1187 }
1188
1189 iks_insert_attrib(request, "from", client->jid->full);
1190 iks_insert_attrib(request, "type", type);
1191 ast_xmpp_client_lock(client);
1192 ast_xmpp_increment_mid(client->mid);
1193 iks_insert_attrib(request, "id", client->mid);
1194 ast_xmpp_client_unlock(client);
1195
1196 return request;
1197}

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

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

◆ xmpp_pubsub_mwi_cb()

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

Callback function for MWI events.

Parameters
datavoid pointer to ast_client structure
sub,msg

Definition at line 1464 of file res_xmpp.c.

1465{
1466 struct ast_xmpp_client *client = data;
1467 char oldmsgs[10], newmsgs[10];
1468 struct ast_mwi_state *mwi_state;
1469
1471 return;
1472 }
1473
1474 mwi_state = stasis_message_data(msg);
1475
1476 if (ast_eid_cmp(&ast_eid_default, &mwi_state->eid)) {
1477 /* If the event didn't originate from this server, don't send it back out. */
1478 return;
1479 }
1480
1481 snprintf(oldmsgs, sizeof(oldmsgs), "%d", mwi_state->old_msgs);
1482 snprintf(newmsgs, sizeof(newmsgs), "%d", mwi_state->new_msgs);
1483 xmpp_pubsub_publish_mwi(client, mwi_state->uniqueid, oldmsgs, newmsgs);
1484}
static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *mailbox, const char *oldmsgs, const char *newmsgs)
Publish MWI to a PubSub node.
Definition: res_xmpp.c:1398
The structure that contains MWI state.
Definition: mwi.h:455
int old_msgs
Definition: mwi.h:460
int new_msgs
Definition: mwi.h:459
const ast_string_field uniqueid
Definition: mwi.h:458
struct ast_eid eid
Definition: mwi.h:463

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

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_publish_device_state()

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

Publish device state to a PubSub node.

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

Definition at line 1429 of file res_xmpp.c.

1431{
1433 iks *request, *state;
1434 char eid_str[20], cachable_str[2];
1435
1436 if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state", cachable))) {
1437 return;
1438 }
1439
1440 if (ast_test_flag(&cfg->global->pubsub, XMPP_PUBSUB_AUTOCREATE)) {
1441 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1442 xmpp_pubsub_create_node(client, "leaf", device, "device_state");
1443 } else {
1444 xmpp_pubsub_create_node(client, NULL, device, NULL);
1445 }
1446 }
1447
1448 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
1449 state = iks_insert(request, "state");
1450 iks_insert_attrib(state, "xmlns", "http://asterisk.org");
1451 iks_insert_attrib(state, "eid", eid_str);
1452 snprintf(cachable_str, sizeof(cachable_str), "%u", cachable);
1453 iks_insert_attrib(state, "cachable", cachable_str);
1454 iks_insert_cdata(state, device_state, strlen(device_state));
1455 ast_xmpp_client_send(client, iks_root(request));
1456 iks_delete(request);
1457}
static iks * xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, const char *node, const char *event_type, unsigned int cachable)
Build the skeleton of a publish.
Definition: res_xmpp.c:1206
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839

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

Referenced by xmpp_pubsub_devstate_cb().

◆ xmpp_pubsub_publish_mwi()

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

Publish MWI to a PubSub node.

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

Definition at line 1398 of file res_xmpp.c.

1400{
1401 char eid_str[20];
1402 iks *mailbox_node, *request;
1403
1404 request = xmpp_pubsub_build_publish_skeleton(client, mailbox, "message_waiting",
1406 if (!request) {
1407 return;
1408 }
1409
1410 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
1411 mailbox_node = iks_insert(request, "mailbox");
1412 iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org");
1413 iks_insert_attrib(mailbox_node, "eid", eid_str);
1414 iks_insert_cdata(iks_insert(mailbox_node, "NEWMSGS"), newmsgs, strlen(newmsgs));
1415 iks_insert_cdata(iks_insert(mailbox_node, "OLDMSGS"), oldmsgs, strlen(oldmsgs));
1416
1417 ast_xmpp_client_send(client, iks_root(request));
1418
1419 iks_delete(request);
1420}

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

Referenced by xmpp_pubsub_mwi_cb().

◆ xmpp_pubsub_purge_nodes()

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

Definition at line 4246 of file res_xmpp.c.

4247{
4248 iks *request = xmpp_pubsub_build_node_request(client, collection_name);
4250 iks_filter_add_rule(client->filter, xmpp_pubsub_delete_node_list, client, IKS_RULE_TYPE,
4251 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid,
4252 IKS_RULE_DONE);
4254 iks_delete(request);
4255}
static iks * xmpp_pubsub_build_node_request(struct ast_xmpp_client *client, const char *collection)
Build the a node request.
Definition: res_xmpp.c:4103
static int xmpp_pubsub_delete_node_list(void *data, ikspak *pak)
Delete pubsub item lists.
Definition: res_xmpp.c:4225

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

Referenced by xmpp_cli_purge_pubsub_nodes().

◆ xmpp_pubsub_receive_node_list()

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

Receive pubsub item lists.

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

Definition at line 4127 of file res_xmpp.c.

4128{
4129 struct ast_xmpp_client *client = data;
4130 iks *item = NULL;
4131
4132 if (iks_has_children(pak->query)) {
4133 item = iks_first_tag(pak->query);
4134 ast_verbose("Connection %s: %s\nNode name: %s\n", client->name, client->jid->partial,
4135 iks_find_attrib(item, "node"));
4136 while ((item = iks_next_tag(item))) {
4137 ast_verbose("Node name: %s\n", iks_find_attrib(item, "node"));
4138 }
4139 }
4140
4141 if (item) {
4142 iks_delete(item);
4143 }
4144
4145
4146 return IKS_FILTER_EAT;
4147}

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

Referenced by xmpp_pubsub_request_nodes().

◆ xmpp_pubsub_request_nodes()

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

Request item list from pubsub.

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

Definition at line 4154 of file res_xmpp.c.

4155{
4156 iks *request = xmpp_pubsub_build_node_request(client, collection);
4157
4158 if (!request) {
4159 ast_log(LOG_ERROR, "Could not request pubsub nodes on client '%s' - IQ could not be created\n", client->name);
4160 return;
4161 }
4162
4163 iks_filter_add_rule(client->filter, xmpp_pubsub_receive_node_list, client, IKS_RULE_TYPE,
4164 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->mid,
4165 IKS_RULE_DONE);
4167 iks_delete(request);
4168
4169}
static int xmpp_pubsub_receive_node_list(void *data, ikspak *pak)
Receive pubsub item lists.
Definition: res_xmpp.c:4127

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

Referenced by xmpp_cli_list_pubsub_nodes().

◆ xmpp_pubsub_subscribe()

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

Subscribe to a PubSub node.

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

Definition at line 1539 of file res_xmpp.c.

1540{
1542 iks *request = xmpp_pubsub_iq_create(client, "set");
1543 iks *pubsub, *subscribe;
1544
1545 if (!cfg || !cfg->global || !request) {
1546 ast_log(LOG_ERROR, "Could not create IQ when creating pubsub subscription on client '%s'\n", client->name);
1547 return;
1548 }
1549
1550 pubsub = iks_insert(request, "pubsub");
1551 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1552 subscribe = iks_insert(pubsub, "subscribe");
1553 iks_insert_attrib(subscribe, "jid", client->jid->partial);
1554 iks_insert_attrib(subscribe, "node", node);
1555 if (ast_test_flag(&cfg->global->pubsub, XMPP_XEP0248)) {
1556 iks *options, *x, *sub_options, *sub_type, *sub_depth, *sub_expire;
1557 options = iks_insert(pubsub, "options");
1558 x = iks_insert(options, "x");
1559 iks_insert_attrib(x, "xmlns", "jabber:x:data");
1560 iks_insert_attrib(x, "type", "submit");
1561 sub_options = iks_insert(x, "field");
1562 iks_insert_attrib(sub_options, "var", "FORM_TYPE");
1563 iks_insert_attrib(sub_options, "type", "hidden");
1564 iks_insert_cdata(iks_insert(sub_options, "value"),
1565 "http://jabber.org/protocol/pubsub#subscribe_options", 51);
1566 sub_type = iks_insert(x, "field");
1567 iks_insert_attrib(sub_type, "var", "pubsub#subscription_type");
1568 iks_insert_cdata(iks_insert(sub_type, "value"), "items", 5);
1569 sub_depth = iks_insert(x, "field");
1570 iks_insert_attrib(sub_depth, "var", "pubsub#subscription_depth");
1571 iks_insert_cdata(iks_insert(sub_depth, "value"), "all", 3);
1572 sub_expire = iks_insert(x, "field");
1573 iks_insert_attrib(sub_expire, "var", "pubsub#expire");
1574 iks_insert_cdata(iks_insert(sub_expire, "value"), "presence", 8);
1575 }
1577 iks_delete(request);
1578}
unsigned char subscribe
Definition: res_corosync.c:243

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

Referenced by xmpp_init_event_distribution().

◆ xmpp_pubsub_unsubscribe()

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

Unsubscribe from a PubSub node.

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

Definition at line 1514 of file res_xmpp.c.

1515{
1516 iks *request = xmpp_pubsub_iq_create(client, "set");
1517 iks *pubsub, *unsubscribe;
1518
1519 if (!request) {
1520 ast_log(LOG_ERROR, "Could not create IQ when creating pubsub unsubscription on client '%s'\n", client->name);
1521 return;
1522 }
1523
1524 pubsub = iks_insert(request, "pubsub");
1525 iks_insert_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
1526 unsubscribe = iks_insert(pubsub, "unsubscribe");
1527 iks_insert_attrib(unsubscribe, "jid", client->jid->partial);
1528 iks_insert_attrib(unsubscribe, "node", node);
1529
1531 iks_delete(request);
1532}
static int unsubscribe(void *obj, void *arg, int flags)

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

Referenced by ast_xmpp_client_disconnect(), and xmpp_init_event_distribution().

◆ xmpp_resource_cmp()

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

Comparator function for XMPP resource.

Definition at line 982 of file res_xmpp.c.

983{
984 struct ast_xmpp_resource *resource1 = obj;
985 const char *resource = arg;
986
987 return !strcmp(resource1->resource, resource) ? CMP_MATCH | CMP_STOP : 0;
988}

References CMP_MATCH, CMP_STOP, and ast_xmpp_resource::resource.

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

◆ xmpp_resource_destructor()

static void xmpp_resource_destructor ( void *  obj)
static

Destructor callback function for XMPP resource.

Definition at line 964 of file res_xmpp.c.

965{
966 struct ast_xmpp_resource *resource = obj;
967
968 if (resource->description) {
969 ast_free(resource->description);
970 }
971}

References ast_free, and ast_xmpp_resource::resource.

Referenced by xmpp_pak_presence().

◆ xmpp_resource_hash()

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

Hashing function for XMPP resource.

Definition at line 974 of file res_xmpp.c.

975{
976 const struct ast_xmpp_resource *resource = obj;
977
978 return flags & OBJ_KEY ? -1 : resource->priority;
979}

References OBJ_KEY, and ast_xmpp_resource::resource.

Referenced by xmpp_client_create_buddy().

◆ xmpp_resource_immediate()

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

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

Definition at line 1751 of file res_xmpp.c.

1752{
1753 return CMP_MATCH | CMP_STOP;
1754}

References CMP_MATCH, and CMP_STOP.

Referenced by get_buddy_status().

◆ xmpp_resource_is_available()

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

Callback function which returns when the resource is available.

Definition at line 3350 of file res_xmpp.c.

3351{
3352 struct ast_xmpp_resource *resource = obj;
3353
3354 return (resource->status == IKS_SHOW_AVAILABLE) ? CMP_MATCH | CMP_STOP : 0;
3355}

References CMP_MATCH, CMP_STOP, and ast_xmpp_resource::resource.

Referenced by xmpp_pak_presence().

◆ xmpp_roster_hook()

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

Hook function called when roster is received from server.

Definition at line 2376 of file res_xmpp.c.

2377{
2379 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2380 struct ast_xmpp_client *client = data;
2381 iks *item;
2382
2383 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, client->name))) {
2384 return IKS_FILTER_EAT;
2385 }
2386
2387 for (item = iks_child(pak->query); item; item = iks_next(item)) {
2388 struct ast_xmpp_buddy *buddy;
2389
2390 if (iks_strcmp(iks_name(item), "item")) {
2391 continue;
2392 }
2393
2394 if (!(buddy = ao2_find(client->buddies, iks_find_attrib(item, "jid"), OBJ_KEY))) {
2395 if (ast_test_flag(&clientcfg->flags, XMPP_AUTOPRUNE)) {
2396 /* The buddy has not been specified in the configuration file, we no longer
2397 * want them on our buddy list or to receive their presence. */
2398 if (xmpp_client_unsubscribe_user(client, iks_find_attrib(item, "jid"))) {
2399 ast_log(LOG_ERROR, "Could not unsubscribe user '%s' on client '%s'\n",
2400 iks_find_attrib(item, "jid"), client->name);
2401 }
2402 continue;
2403 }
2404
2405 if (!(buddy = xmpp_client_create_buddy(client->buddies, iks_find_attrib(item, "jid")))) {
2406 ast_log(LOG_ERROR, "Could not allocate buddy '%s' on client '%s'\n", iks_find_attrib(item, "jid"),
2407 client->name);
2408 continue;
2409 }
2410 }
2411
2412 /* Determine if we need to subscribe to their presence or not */
2413 if (!iks_strcmp(iks_find_attrib(item, "subscription"), "none") ||
2414 !iks_strcmp(iks_find_attrib(item, "subscription"), "from")) {
2415 buddy->subscribe = 1;
2416 } else {
2417 buddy->subscribe = 0;
2418 }
2419
2420 ao2_ref(buddy, -1);
2421 }
2422
2423 /* If autoregister is enabled we need to go through every buddy that we need to subscribe to and do so */
2424 if (ast_test_flag(&clientcfg->flags, XMPP_AUTOREGISTER)) {
2426 }
2427
2429
2430 return IKS_FILTER_EAT;
2431}
static int xmpp_client_unsubscribe_user(struct ast_xmpp_client *client, const char *user)
Helper function which unsubscribes a user and removes them from the roster.
Definition: res_xmpp.c:2318

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

Referenced by xmpp_connect_hook().

◆ xmpp_send_cb()

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

Definition at line 2255 of file res_xmpp.c.

2256{
2258 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2259 char *sender, *dest;
2260 int res;
2261
2262 sender = ast_strdupa(from);
2263 strsep(&sender, ":");
2264 dest = ast_strdupa(to);
2265 strsep(&dest, ":");
2266
2267 if (ast_strlen_zero(sender)) {
2268 ast_log(LOG_ERROR, "MESSAGE(from) of '%s' invalid for XMPP\n", from);
2269 return -1;
2270 }
2271
2272 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, sender))) {
2273 ast_log(LOG_WARNING, "Could not finder account to send from as '%s'\n", sender);
2274 return -1;
2275 }
2276
2277 ast_debug(1, "Sending message to '%s' from '%s'\n", dest, clientcfg->name);
2278
2279 if ((res = ast_xmpp_client_send_message(clientcfg->client, dest, ast_msg_get_body(msg))) != IKS_OK) {
2280 ast_log(LOG_WARNING, "Failed to send XMPP message (%d).\n", res);
2281 }
2282
2283 return res == IKS_OK ? 0 : -1;
2284}
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: main/message.c:557

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

◆ xmpp_send_exec()

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

Definition at line 1967 of file res_xmpp.c.

1968{
1970 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
1971 char *s;
1973 AST_APP_ARG(sender);
1974 AST_APP_ARG(recipient);
1976 );
1977
1978 if (ast_strlen_zero(data)) {
1979 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
1980 return -1;
1981 }
1982 s = ast_strdupa(data);
1983
1985
1986 if ((args.argc < 3) || ast_strlen_zero(args.message) || !strchr(args.recipient, '@')) {
1987 ast_log(LOG_WARNING, "%s requires arguments (account,jid,message)\n", app_ajisend);
1988 return -1;
1989 }
1990
1991 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
1992 ast_log(LOG_WARNING, "Could not find sender connection: '%s'\n", args.sender);
1993 return -1;
1994 }
1995
1996 ast_xmpp_client_send_message(clientcfg->client, args.recipient, args.message);
1997
1998 return 0;
1999}

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

Referenced by load_module().

◆ xmpp_send_stream_header()

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

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

Definition at line 2651 of file res_xmpp.c.

2652{
2653 char *namespace = ast_test_flag(&cfg->flags, XMPP_COMPONENT) ? "jabber:component:accept" : "jabber:client";
2654 char msg[91 + strlen(namespace) + 6 + strlen(to) + 16 + 1];
2655
2656 snprintf(msg, sizeof(msg), "<?xml version='1.0'?>"
2657 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='"
2658 "%s' to='%s' version='1.0'>", namespace, to);
2659
2660 return xmpp_client_send_raw_message(client, msg);
2661}

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

Referenced by xmpp_client_authenticating(), and xmpp_client_requested_tls().

◆ xmpp_sendgroup_exec()

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

Application to send a message to a groupchat.

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

Definition at line 2008 of file res_xmpp.c.

2009{
2011 RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
2012 char *s, nick[XMPP_MAX_RESJIDLEN];
2014 AST_APP_ARG(sender);
2015 AST_APP_ARG(groupchat);
2017 AST_APP_ARG(nick);
2018 );
2019
2020 if (ast_strlen_zero(data)) {
2021 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
2022 return -1;
2023 }
2024 s = ast_strdupa(data);
2025
2027 if ((args.argc < 3) || (args.argc > 4) || ast_strlen_zero(args.message) || !strchr(args.groupchat, '@')) {
2028 ast_log(LOG_ERROR, "%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
2029 return -1;
2030 }
2031
2032 if (!cfg || !cfg->clients || !(clientcfg = xmpp_config_find(cfg->clients, args.sender))) {
2033 ast_log(LOG_ERROR, "Could not find sender connection: '%s'\n", args.sender);
2034 return -1;
2035 }
2036
2037 if (ast_strlen_zero(args.nick) || args.argc == 3) {
2038 if (ast_test_flag(&clientcfg->flags, XMPP_COMPONENT)) {
2039 snprintf(nick, sizeof(nick), "asterisk");
2040 } else {
2041 snprintf(nick, sizeof(nick), "%s", clientcfg->client->jid->user);
2042 }
2043 } else {
2044 snprintf(nick, sizeof(nick), "%s", args.nick);
2045 }
2046
2047 ast_xmpp_chatroom_send(clientcfg->client, nick, args.groupchat, args.message);
2048
2049 return 0;
2050}
int ast_xmpp_chatroom_send(struct ast_xmpp_client *client, const char *nickname, const char *address, const char *message)
Send a message to an XMPP multi-user chatroom.
Definition: res_xmpp.c:1144

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

Referenced by load_module().

◆ xmpp_show_buddies()

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

Definition at line 4539 of file res_xmpp.c.

4540{
4542 struct ao2_iterator i;
4543 struct ast_xmpp_client_config *clientcfg;
4544
4545 switch (cmd) {
4546 case CLI_INIT:
4547 e->command = "xmpp show buddies";
4548 e->usage =
4549 "Usage: xmpp show buddies\n"
4550 " Shows buddy lists of our clients\n";
4551 return NULL;
4552 case CLI_GENERATE:
4553 return NULL;
4554 }
4555
4556 if (!cfg || !cfg->clients) {
4557 return NULL;
4558 }
4559
4560 ast_cli(a->fd, "XMPP buddy lists\n");
4561
4562 i = ao2_iterator_init(cfg->clients, 0);
4563 while ((clientcfg = ao2_iterator_next(&i))) {
4564 struct ao2_iterator bud;
4565 struct ast_xmpp_buddy *buddy;
4566
4567 ast_cli(a->fd, "Client: %s\n", clientcfg->name);
4568
4569 bud = ao2_iterator_init(clientcfg->client->buddies, 0);
4570 while ((buddy = ao2_iterator_next(&bud))) {
4571 struct ao2_iterator res;
4573
4574 ast_cli(a->fd, "\tBuddy:\t%s\n", buddy->id);
4575
4576 res = ao2_iterator_init(buddy->resources, 0);
4577 while ((resource = ao2_iterator_next(&res))) {
4578 ast_cli(a->fd, "\t\tResource: %s\n", resource->resource);
4579 ast_cli(a->fd, "\t\t\tnode: %s\n", resource->caps.node);
4580 ast_cli(a->fd, "\t\t\tversion: %s\n", resource->caps.version);
4581 ast_cli(a->fd, "\t\t\tGoogle Talk capable: %s\n", resource->caps.google ? "yes" : "no");
4582 ast_cli(a->fd, "\t\t\tJingle capable: %s\n", resource->caps.jingle ? "yes" : "no");
4583
4584 ao2_ref(resource, -1);
4585 }
4587
4588 ao2_ref(buddy, -1);
4589 }
4591
4592 ao2_ref(clientcfg, -1);
4593 }
4595
4596 return CLI_SUCCESS;
4597}

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

◆ xmpp_show_clients()

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

Definition at line 4463 of file res_xmpp.c.

4464{
4466 struct ao2_iterator i;
4467 struct ast_xmpp_client_config *clientcfg;
4468
4469 switch (cmd) {
4470 case CLI_INIT:
4471 e->command = "xmpp show connections";
4472 e->usage =
4473 "Usage: xmpp show connections\n"
4474 " Shows state of client and component connections\n";
4475 return NULL;
4476 case CLI_GENERATE:
4477 return NULL;
4478 }
4479
4480 if (!cfg || !cfg->clients) {
4481 return NULL;
4482 }
4483
4484 ast_cli(a->fd, "Jabber Users and their status:\n");
4485
4486 i = ao2_iterator_init(cfg->clients, 0);
4487 while ((clientcfg = ao2_iterator_next(&i))) {
4488 char *state;
4489
4490 switch (clientcfg->client->state) {
4492 state = "Disconnecting";
4493 break;
4495 state = "Disconnected";
4496 break;
4498 state = "Connecting";
4499 break;
4501 state = "Waiting to request TLS";
4502 break;
4504 state = "Requested TLS";
4505 break;
4507 state = "Waiting to authenticate";
4508 break;
4510 state = "Authenticating";
4511 break;
4512 case XMPP_STATE_ROSTER:
4513 state = "Retrieving roster";
4514 break;
4516 state = "Connected";
4517 break;
4518 default:
4519 state = "Unknown";
4520 }
4521
4522 ast_cli(a->fd, " [%s] %s - %s\n", clientcfg->name, clientcfg->user, state);
4523
4524 ao2_ref(clientcfg, -1);
4525 }
4527
4528 ast_cli(a->fd, "----\n");
4529 ast_cli(a->fd, " Number of clients: %d\n", ao2_container_count(cfg->clients));
4530
4531 return CLI_SUCCESS;
4532}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
@ XMPP_STATE_CONNECTING
Definition: xmpp.h:74

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

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk XMPP Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static

Definition at line 4832 of file res_xmpp.c.

◆ app_ajijoin

const char* app_ajijoin = "JabberJoin"
static

Definition at line 648 of file res_xmpp.c.

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

◆ app_ajileave

const char* app_ajileave = "JabberLeave"
static

Definition at line 649 of file res_xmpp.c.

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

◆ app_ajisend

const char* app_ajisend = "JabberSend"
static

Definition at line 645 of file res_xmpp.c.

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

◆ app_ajisendgroup

const char* app_ajisendgroup = "JabberSendGroup"
static

Definition at line 646 of file res_xmpp.c.

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

◆ app_ajistatus

const char* app_ajistatus = "JabberStatus"
static

Definition at line 647 of file res_xmpp.c.

Referenced by unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4832 of file res_xmpp.c.

◆ client_option

struct aco_type client_option
static

Definition at line 939 of file res_xmpp.c.

◆ client_options

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

Definition at line 950 of file res_xmpp.c.

Referenced by load_module().

◆ debug

int debug
static

◆ global_option

struct aco_type global_option
static

Definition at line 929 of file res_xmpp.c.

◆ global_options

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

Definition at line 937 of file res_xmpp.c.

Referenced by load_module().

◆ jabberreceive_function

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

Definition at line 2208 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ jabberstatus_function

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

Definition at line 1835 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ message_received_condition

ast_cond_t message_received_condition
static

Definition at line 651 of file res_xmpp.c.

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

◆ messagelock

ast_mutex_t messagelock
static

Definition at line 652 of file res_xmpp.c.

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

◆ msg_tech

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

Definition at line 2286 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ res_xmpp_conf

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

Definition at line 952 of file res_xmpp.c.

◆ xmpp_cli

struct ast_cli_entry xmpp_cli[]
static

Definition at line 4599 of file res_xmpp.c.

Referenced by load_module(), and unload_module().

◆ xmpp_pak_handlers

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

Referenced by xmpp_action_hook().

◆ xmpp_state_handlers

const struct xmpp_state_handler xmpp_state_handlers[]
static

Referenced by xmpp_action_hook().