Asterisk - The Open Source Telephony Project GIT-master-a63eec2
Loading...
Searching...
No Matches
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)
 
#define BUDDY_NOT_IN_ROSTER   7
 
#define BUDDY_OFFLINE   6
 
#define CLIENT_BUCKETS   53
 Number of buckets for client connections.
 
#define RESOURCE_BUCKETS   53
 Number of buckets for resources (per buddy)
 
#define STATUS_DISAPPEAR   6
 Status for a disappearing buddy.
 
#define XMPP_TLS_NS   "urn:ietf:params:xml:ns:xmpp-tls"
 Namespace for TLS support.
 

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.
 
int ast_xmpp_chatroom_join (struct ast_xmpp_client *client, const char *room, const char *nickname)
 Join an XMPP multi-user chatroom.
 
int ast_xmpp_chatroom_leave (struct ast_xmpp_client *client, const char *room, const char *nickname)
 Leave an XMPP multi-user chatroom.
 
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.
 
static void * ast_xmpp_client_config_alloc (const char *cat)
 Allocator function for configuration.
 
static void ast_xmpp_client_config_destructor (void *obj)
 Destructor function for configuration.
 
int ast_xmpp_client_disconnect (struct ast_xmpp_client *client)
 Disconnect an XMPP client connection.
 
struct ast_xmpp_clientast_xmpp_client_find (const char *name)
 Find an XMPP client connection using a given name.
 
void ast_xmpp_client_lock (struct ast_xmpp_client *client)
 Lock an XMPP client connection.
 
int ast_xmpp_client_send (struct ast_xmpp_client *client, iks *stanza)
 Send an XML stanza out using an established XMPP client connection.
 
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.
 
void ast_xmpp_client_unlock (struct ast_xmpp_client *client)
 Unlock an XMPP client connection.
 
void ast_xmpp_client_unref (struct ast_xmpp_client *client)
 Release XMPP client connection reference.
 
void ast_xmpp_increment_mid (char *mid)
 Helper function which increments the message identifier.
 
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.
 
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.
 
static int xmpp_buddy_cmp (void *obj, void *arg, int flags)
 Comparator function for XMPP buddy.
 
static void xmpp_buddy_destructor (void *obj)
 Destructor callback function for XMPP buddy.
 
static int xmpp_buddy_hash (const void *obj, const int flags)
 Hashing function for XMPP buddy.
 
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.
 
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.
 
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.
 
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.
 
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.
 
static struct ast_xmpp_clientxmpp_client_alloc (const char *name)
 Allocator function for ast_xmpp_client.
 
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.
 
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.
 
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.
 
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.
 
static void xmpp_client_change_state (struct ast_xmpp_client *client, int state)
 Internal function which changes the XMPP client state.
 
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.
 
static void xmpp_client_destructor (void *obj)
 Destructor callback function for XMPP client.
 
static void * xmpp_client_find_or_create (const char *category)
 Look up existing client or create a new one.
 
static int xmpp_client_receive (struct ast_xmpp_client *client, unsigned int timeout)
 Internal function which receives data from the XMPP client connection.
 
static int xmpp_client_reconnect (struct ast_xmpp_client *client)
 Internal function used to reconnect an XMPP client to its server.
 
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.
 
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.
 
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.
 
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.
 
static int xmpp_client_send_raw_message (struct ast_xmpp_client *client, const char *message)
 Internal function which sends a raw message.
 
static int xmpp_client_service_discovery_get_hook (void *data, ikspak *pak)
 Hook function called when client receives a service discovery get message.
 
static int xmpp_client_service_discovery_result_hook (void *data, ikspak *pak)
 Hook function called when client receives a service discovery result message.
 
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.
 
static int xmpp_client_subscribe_user (void *obj, void *arg, int flags)
 Callback function which subscribes to a user if needed.
 
static void * xmpp_client_thread (void *data)
 XMPP client connection thread.
 
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.
 
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.
 
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.
 
static int xmpp_component_register_get_hook (void *data, ikspak *pak)
 Hook function called when the component is queried about registration.
 
static int xmpp_component_register_set_hook (void *data, ikspak *pak)
 Hook function called when someone registers to the component.
 
static int xmpp_component_service_discovery_get_hook (void *data, ikspak *pak)
 Hook function called when component receives a service discovery get message.
 
static int xmpp_component_service_discovery_items_hook (void *data, ikspak *pak)
 Hook function called when we receive a service discovery items request.
 
static void * xmpp_config_alloc (void)
 Allocator for XMPP configuration.
 
static int xmpp_config_cmp (void *obj, void *arg, int flags)
 Comparator function for configuration.
 
static void xmpp_config_destructor (void *obj)
 Destructor for XMPP configuration.
 
static void * xmpp_config_find (struct ao2_container *tmp_container, const char *category)
 Find function for configuration.
 
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.
 
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.
 
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.
 
static int xmpp_is_secure (struct ast_xmpp_client *client)
 Helper function which returns whether an XMPP client connection is secure or not.
 
static int xmpp_join_exec (struct ast_channel *chan, const char *data)
 Application to join a chat room.
 
static int xmpp_leave_exec (struct ast_channel *chan, const char *data)
 Application to leave a chat room.
 
static void xmpp_log_hook (void *data, const char *xmpp, size_t size, int incoming)
 Logging hook function.
 
static void xmpp_message_destroy (struct ast_xmpp_message *message)
 Destroy function for XMPP messages.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
static void xmpp_pubsub_create_affiliations (struct ast_xmpp_client *client, const char *node)
 Add Owner affiliations for pubsub node.
 
static void xmpp_pubsub_create_collection (struct ast_xmpp_client *client, const char *collection_name)
 Create a PubSub collection node.
 
static void xmpp_pubsub_create_leaf (struct ast_xmpp_client *client, const char *collection_name, const char *leaf_name)
 Create a PubSub leaf node.
 
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.
 
static void xmpp_pubsub_delete_node (struct ast_xmpp_client *client, const char *node_name)
 Delete a PubSub node.
 
static int xmpp_pubsub_delete_node_list (void *data, ikspak *pak)
 Delete pubsub item lists.
 
static void xmpp_pubsub_devstate_cb (void *data, struct stasis_subscription *sub, struct stasis_message *msg)
 Callback function for device state events.
 
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.
 
static iks * xmpp_pubsub_iq_create (struct ast_xmpp_client *client, const char *type)
 Create an IQ packet.
 
static void xmpp_pubsub_mwi_cb (void *data, struct stasis_subscription *sub, struct stasis_message *msg)
 Callback function for MWI events.
 
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.
 
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.
 
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.
 
static void xmpp_pubsub_request_nodes (struct ast_xmpp_client *client, const char *collection)
 Request item list from pubsub.
 
static void xmpp_pubsub_subscribe (struct ast_xmpp_client *client, const char *node)
 Subscribe to a PubSub node.
 
static void xmpp_pubsub_unsubscribe (struct ast_xmpp_client *client, const char *node)
 Unsubscribe from a PubSub node.
 
static int xmpp_resource_cmp (void *obj, void *arg, int flags)
 Comparator function for XMPP resource.
 
static void xmpp_resource_destructor (void *obj)
 Destructor callback function for XMPP resource.
 
static int xmpp_resource_hash (const void *obj, const int flags)
 Hashing function for XMPP resource.
 
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.
 
static int xmpp_resource_is_available (void *obj, void *arg, int flags)
 Callback function which returns when the resource is available.
 
static int xmpp_roster_hook (void *data, ikspak *pak)
 Hook function called when roster is received from server.
 
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.
 
static int xmpp_sendgroup_exec (struct ast_channel *chan, const char *data)
 Application to send a message to a groupchat.
 
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 = ASTERISK_GPL_KEY , .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.
 
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...
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
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.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#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.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#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 struct @519 args
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
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:2280
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:978
#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 phoneprov_users.conf
int done

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.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
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

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:1201
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:2235
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::@311 messages
const ast_string_field name
Definition xmpp.h:123
char * from
Definition xmpp.h:102
struct ast_xmpp_message::@310 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,...)

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

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));
4769 aco_option_register(&cfg_info, "context", ACO_EXACT, client_options, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_xmpp_client_config, context));
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:1562
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:3135
#define ARRAY_LEN(a)
Definition utils.h:703
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(), 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:1982
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:2014
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1643
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1903
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:249

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}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition astobj2.h:859
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7698
#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[]
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
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_pak_handler::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}
enum queue_result id
Definition app_queue.c:1767
@ 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.
static void xmpp_client_destructor(void *obj)
Destructor callback function for XMPP client.
Definition res_xmpp.c:680
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}
@ 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, 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:218
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:629
#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:603
#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.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.

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

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]
static struct agi_command commands[]
AGI commands list.
Definition res_agi.c:3877

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}
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, 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()
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
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.
@ 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:1090
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:1144
#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:1038
#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}
#define ast_verbose(...)

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.
#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.
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
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.
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
static int delete_old_messages(struct ast_xmpp_client *client, char *from)
Definition res_xmpp.c:2221
A message.
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.
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)
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
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.
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
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
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:1217
The structure that contains device state.
enum ast_device_state state
const struct ast_eid * eid
The EID of the server where this message originated.
enum ast_devstate_cache cachable
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
Definition utils.c:3130

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_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.
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.
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:850
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
Definition utils.c:3113

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, 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_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:2875

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(), 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(), 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

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, ast_xmpp_resource::priority, 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.

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, 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 = ASTERISK_GPL_KEY , .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.

939 {
940 .type = ACO_ITEM,
941 .name = "client",
942 .category_match = ACO_BLACKLIST_EXACT,
943 .category = "general",
944 .item_alloc = ast_xmpp_client_config_alloc,
945 .item_find = xmpp_config_find,
946 .item_prelink = xmpp_config_prelink,
947 .item_offset = offsetof(struct xmpp_config, clients),
948};
@ ACO_ITEM
@ ACO_BLACKLIST_EXACT
static void * ast_xmpp_client_config_alloc(const char *cat)
Allocator function for configuration.
Definition res_xmpp.c:806
static int xmpp_config_prelink(void *newitem)
Definition res_xmpp.c:877

◆ 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.

929 {
930 .type = ACO_GLOBAL,
931 .name = "global",
932 .item_offset = offsetof(struct xmpp_config, global),
933 .category_match = ACO_WHITELIST_EXACT,
934 .category = "general",
935};
@ ACO_GLOBAL
@ ACO_WHITELIST_EXACT

◆ 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.

2208 {
2209 .name = "JABBER_RECEIVE",
2210 .read = acf_jabberreceive_read,
2211};

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.

1835 {
1836 .name = "JABBER_STATUS",
1837 .read = acf_jabberstatus_read,
1838};

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.

2286 {
2287 .name = "xmpp",
2288 .msg_send = xmpp_send_cb,
2289};

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.

952 {
953 .filename = "xmpp.conf",
954 .alias = "jabber.conf",
956};

◆ xmpp_cli

struct ast_cli_entry xmpp_cli[]
static

Definition at line 4599 of file res_xmpp.c.

4599 {
4600 AST_CLI_DEFINE(xmpp_do_set_debug, "Enable/Disable Jabber debug"),
4601 AST_CLI_DEFINE(xmpp_show_clients, "Show state of clients and components"),
4602 AST_CLI_DEFINE(xmpp_show_buddies, "Show buddy lists of our clients"),
4603 AST_CLI_DEFINE(xmpp_cli_create_collection, "Creates a PubSub node collection."),
4604 AST_CLI_DEFINE(xmpp_cli_list_pubsub_nodes, "Lists PubSub nodes"),
4605 AST_CLI_DEFINE(xmpp_cli_create_leafnode, "Creates a PubSub leaf node"),
4606 AST_CLI_DEFINE(xmpp_cli_delete_pubsub_node, "Deletes a PubSub node"),
4607 AST_CLI_DEFINE(xmpp_cli_purge_pubsub_nodes, "Purges PubSub nodes"),
4608};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
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.
Definition res_xmpp.c:4264
static char * xmpp_do_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_xmpp.c:4429
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.
Definition res_xmpp.c:4387
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.
Definition res_xmpp.c:4178
static char * xmpp_show_clients(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_xmpp.c:4463
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.
Definition res_xmpp.c:4347
static char * xmpp_show_buddies(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_xmpp.c:4539
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.
Definition res_xmpp.c:4309

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().