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

Motif Jingle Channel Driver. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <iksemel.h>
#include <pthread.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config_options.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/stringfields.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/xmpp.h"
#include "asterisk/endpoints.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/format_cache.h"

Go to the source code of this file.

Data Structures

struct  jingle_action_handler
 Defined handlers for different Jingle actions. More...
 
struct  jingle_config
 
struct  jingle_endpoint
 Endpoint which contains configuration information and active sessions. More...
 
struct  jingle_endpoint_state
 Endpoint state information. More...
 
struct  jingle_reason_mapping
 Reason text <-> cause code mapping. More...
 
struct  jingle_session
 Session which contains information about an active session. More...
 

Macros

#define DEFAULT_MAX_ICE_CANDIDATES   "10"
 Default maximum number of ICE candidates we will offer. More...
 
#define DEFAULT_MAX_PAYLOADS   "30"
 Default maximum number of payloads we will offer. More...
 
#define ENDPOINT_BUCKETS   37
 Number of buckets for endpoints. More...
 
#define GOOGLE_PHONE_NS   "http://www.google.com/session/phone"
 Namespace for Google Phone description. More...
 
#define GOOGLE_SESSION_NS   "http://www.google.com/session"
 Namespace for Google Session. More...
 
#define GOOGLE_TRANSPORT_NS   "http://www.google.com/transport/p2p"
 Namespace for Google Talk ICE-UDP. More...
 
#define GOOGLE_TRANSPORT_RAW_NS   "http://www.google.com/transport/raw-udp"
 Namespace for Google Talk Raw UDP. More...
 
#define GOOGLE_VIDEO_NS   "http://www.google.com/session/video"
 Namespace for Google Video description. More...
 
#define JINGLE_ICE_UDP_NS   "urn:xmpp:jingle:transports:ice-udp:1"
 Namespace for Jingle ICE-UDP. More...
 
#define JINGLE_NS   "urn:xmpp:jingle:1"
 Namespace for Jingle itself. More...
 
#define JINGLE_RTP_INFO_NS   "urn:xmpp:jingle:apps:rtp:info:1"
 Namespace for Jingle RTP info. More...
 
#define JINGLE_RTP_NS   "urn:xmpp:jingle:apps:rtp:1"
 Namespace for Jingle RTP sessions. More...
 
#define SESSION_BUCKETS   37
 Number of buckets for sessions, on a per-endpoint basis. More...
 
#define XMPP_STANZAS_NS   "urn:ietf:params:xml:ns:xmpp-stanzas"
 Namespace for XMPP stanzas. More...
 

Enumerations

enum  jingle_transport { JINGLE_TRANSPORT_ICE_UDP = 3, JINGLE_TRANSPORT_GOOGLE_V2 = 2, JINGLE_TRANSPORT_GOOGLE_V1 = 1, JINGLE_TRANSPORT_NONE = 0 }
 The various transport methods supported, from highest priority to lowest priority when doing fallback. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static AO2_GLOBAL_OBJ_STATIC (globals)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 CONFIG_INFO_STANDARD (cfg_info, globals, jingle_config_alloc,.files=ACO_FILES(&jingle_conf),)
 
static int custom_connection_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Custom handler for connection. More...
 
static int custom_group_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Custom handler for groups. More...
 
static int custom_transport_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Custom handler for transport. More...
 
static int jingle_action_hook (void *data, ikspak *pak)
 Callback for when a Jingle action is received from an endpoint. More...
 
static void jingle_action_session_accept (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'session-accept' action. More...
 
static void jingle_action_session_info (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'session-info' action. More...
 
static void jingle_action_session_initiate (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Action handlers. More...
 
static void jingle_action_session_terminate (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'session-terminate' action. More...
 
static void jingle_action_transport_info (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'transport-info' action. More...
 
static int jingle_add_content (struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport, const char *name, enum ast_media_type type, struct ast_rtp_instance *rtp, iks **payloads)
 Helper function which adds content to a description. More...
 
static int jingle_add_google_candidates_to_transport (struct ast_rtp_instance *rtp, iks *transport, iks **candidates, unsigned int video, enum jingle_transport transport_type, unsigned int maximum)
 Internal helper function which adds Google candidates to a transport node. More...
 
static int jingle_add_ice_udp_candidates_to_transport (struct ast_rtp_instance *rtp, iks *transport, iks **candidates, unsigned int maximum)
 Internal helper function which adds ICE-UDP candidates to a transport node. More...
 
static int jingle_add_payloads_to_description (struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_media_type type)
 Internal helper function which adds payloads to a description. More...
 
static struct jingle_sessionjingle_alloc (struct jingle_endpoint *endpoint, const char *from, const char *sid)
 Internal helper function used to allocate Jingle session on an endpoint. More...
 
static int jingle_answer (struct ast_channel *ast)
 Function called by core when we should answer a Jingle session. More...
 
static int jingle_call (struct ast_channel *ast, const char *dest, int timeout)
 Function called by core to actually start calling a remote party. More...
 
static void * jingle_config_alloc (void)
 Allocator called when module configuration should appear. More...
 
static void jingle_config_destructor (void *obj)
 Destructor called when module configuration goes away. More...
 
static int jingle_digit_begin (struct ast_channel *chan, char digit)
 Function called by core to start a DTMF digit. More...
 
static int jingle_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 Function called by core to stop a DTMF digit. More...
 
static void jingle_enable_video (struct jingle_session *session)
 Internal helper function which enables video support on a sesson if possible. More...
 
static void * jingle_endpoint_alloc (const char *cat)
 Allocator function for Jingle endpoints. More...
 
static int jingle_endpoint_cmp (void *obj, void *arg, int flags)
 Comparator function for Jingle endpoints. More...
 
static void jingle_endpoint_destructor (void *obj)
 Destructor for Jingle endpoints. More...
 
static void * jingle_endpoint_find (struct ao2_container *tmp_container, const char *category)
 Find function for Jingle endpoints. More...
 
static int jingle_endpoint_hash (const void *obj, const int flags)
 Hashing function for Jingle endpoints. More...
 
static struct jingle_endpoint_statejingle_endpoint_state_create (void)
 Allocator function for Jingle endpoint state. More...
 
static void jingle_endpoint_state_destructor (void *obj)
 Destructor for Jingle endpoint state. More...
 
static struct jingle_endpoint_statejingle_endpoint_state_find_or_create (const char *category)
 State find/create function. More...
 
static int jingle_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 Function called by core to change the underlying owner channel. More...
 
static void jingle_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
 Function called by RTP engine to get peer capabilities. More...
 
static enum ast_rtp_glue_result jingle_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
 Function called by RTP engine to get local RTP peer. More...
 
static int jingle_hangup (struct ast_channel *ast)
 Function called by core to hang up a Jingle session. More...
 
static int jingle_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
 Function called by core to ask the channel to indicate some sort of condition. More...
 
static int jingle_interpret_content (struct jingle_session *session, ikspak *pak)
 Helper function which locates content stanzas and interprets them. More...
 
static int jingle_interpret_description (struct jingle_session *session, iks *description, const char *name, struct ast_rtp_instance **rtp)
 Helper function which handles content descriptions. More...
 
static int jingle_interpret_google_transport (struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
 Helper function which handles Google transport information. More...
 
static int jingle_interpret_ice_udp_transport (struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
 Helper function which handles ICE-UDP transport information. More...
 
static struct ast_channeljingle_new (struct jingle_endpoint *endpoint, struct jingle_session *session, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
 Function called to create a new Jingle Asterisk channel. More...
 
static int jingle_outgoing_hook (void *data, ikspak *pak)
 Callback for when a response is received for an outgoing session-initiate message. More...
 
static void jingle_queue_hangup_with_cause (struct jingle_session *session, int cause)
 Helper function which queues a hangup frame with cause code. More...
 
static struct ast_framejingle_read (struct ast_channel *ast)
 Function called by core to read any waiting frames. More...
 
static struct ast_channeljingle_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 Function called by core to create a new outgoing Jingle session. More...
 
static void jingle_send_error_response (struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
 Internal helper function which sends an error response. More...
 
static void jingle_send_response (struct ast_xmpp_client *connection, ikspak *pak)
 Internal helper function which sends a response. More...
 
static void jingle_send_session_accept (struct jingle_session *session)
 Internal function which sends a session-accept message. More...
 
static void jingle_send_session_action (struct jingle_session *session, const char *action)
 Internal function which sends a complete session message. More...
 
static void jingle_send_session_info (struct jingle_session *session, const char *info)
 Internal function which sends a session-info message. More...
 
static void jingle_send_session_initiate (struct jingle_session *session)
 Internal function which sends a session-inititate message. More...
 
static void jingle_send_session_terminate (struct jingle_session *session, const char *reasontext)
 Internal function which sends a session-terminate message. More...
 
static void jingle_send_transport_info (struct jingle_session *session, const char *from)
 Internal function which sends a transport-info message. More...
 
static int jingle_sendtext (struct ast_channel *chan, const char *text)
 Function called by core to send text to the remote party of the Jingle session. More...
 
static int jingle_session_cmp (void *obj, void *arg, int flags)
 Comparator function for Jingle sessions. More...
 
static void jingle_session_destructor (void *obj)
 Destructor for Jingle sessions. More...
 
static int jingle_session_hash (const void *obj, const int flags)
 Hashing function for Jingle sessions. More...
 
static struct ast_channeljingle_session_lock_full (struct jingle_session *pvt)
 
static void jingle_set_owner (struct jingle_session *session, struct ast_channel *chan)
 Set the channel owner on the jingle_session object and related objects. More...
 
static int jingle_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active)
 Function called by RTP engine to change where the remote party should send media. More...
 
static int jingle_write (struct ast_channel *ast, struct ast_frame *frame)
 Function called by core to write frames. More...
 
static int load_module (void)
 Load the module. More...
 
static int reload (void)
 Reload module. More...
 
static int unload_module (void)
 Unload the jingle channel from Asterisk. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Motif Jingle Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_xmpp", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char channel_type [] = "Motif"
 
static struct aco_type endpoint_option
 
struct aco_typeendpoint_options [] = ACO_TYPES(&endpoint_option)
 
static const struct jingle_action_handler jingle_action_handlers []
 
struct aco_file jingle_conf
 
static const struct jingle_reason_mapping jingle_reason_mappings []
 
static struct ast_rtp_glue jingle_rtp_glue
 Local glue for interacting with the RTP engine core. More...
 
static struct ast_channel_tech jingle_tech
 PBX interface structure for channel registration. More...
 
static struct ast_sched_contextsched
 

Detailed Description

Motif Jingle Channel Driver.

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

Iksemel http://iksemel.jabberstudio.org/

Definition in file chan_motif.c.

Macro Definition Documentation

◆ DEFAULT_MAX_ICE_CANDIDATES

#define DEFAULT_MAX_ICE_CANDIDATES   "10"

Default maximum number of ICE candidates we will offer.

Definition at line 220 of file chan_motif.c.

Referenced by load_module().

◆ DEFAULT_MAX_PAYLOADS

#define DEFAULT_MAX_PAYLOADS   "30"

Default maximum number of payloads we will offer.

Definition at line 223 of file chan_motif.c.

Referenced by load_module().

◆ ENDPOINT_BUCKETS

#define ENDPOINT_BUCKETS   37

Number of buckets for endpoints.

Definition at line 226 of file chan_motif.c.

Referenced by jingle_config_alloc().

◆ GOOGLE_PHONE_NS

#define GOOGLE_PHONE_NS   "http://www.google.com/session/phone"

Namespace for Google Phone description.

Definition at line 253 of file chan_motif.c.

Referenced by jingle_add_content(), jingle_add_payloads_to_description(), and jingle_interpret_content().

◆ GOOGLE_SESSION_NS

#define GOOGLE_SESSION_NS   "http://www.google.com/session"

◆ GOOGLE_TRANSPORT_NS

#define GOOGLE_TRANSPORT_NS   "http://www.google.com/transport/p2p"

Namespace for Google Talk ICE-UDP.

Definition at line 244 of file chan_motif.c.

Referenced by jingle_add_content(), jingle_add_google_candidates_to_transport(), and jingle_interpret_content().

◆ GOOGLE_TRANSPORT_RAW_NS

#define GOOGLE_TRANSPORT_RAW_NS   "http://www.google.com/transport/raw-udp"

Namespace for Google Talk Raw UDP.

Definition at line 247 of file chan_motif.c.

◆ GOOGLE_VIDEO_NS

#define GOOGLE_VIDEO_NS   "http://www.google.com/session/video"

Namespace for Google Video description.

Definition at line 256 of file chan_motif.c.

Referenced by jingle_interpret_content().

◆ JINGLE_ICE_UDP_NS

#define JINGLE_ICE_UDP_NS   "urn:xmpp:jingle:transports:ice-udp:1"

Namespace for Jingle ICE-UDP.

Definition at line 241 of file chan_motif.c.

Referenced by jingle_add_content(), jingle_add_ice_udp_candidates_to_transport(), and jingle_interpret_content().

◆ JINGLE_NS

#define JINGLE_NS   "urn:xmpp:jingle:1"

◆ JINGLE_RTP_INFO_NS

#define JINGLE_RTP_INFO_NS   "urn:xmpp:jingle:apps:rtp:info:1"

Namespace for Jingle RTP info.

Definition at line 238 of file chan_motif.c.

Referenced by jingle_action_session_info().

◆ JINGLE_RTP_NS

#define JINGLE_RTP_NS   "urn:xmpp:jingle:apps:rtp:1"

Namespace for Jingle RTP sessions.

Definition at line 235 of file chan_motif.c.

Referenced by jingle_add_content(), and jingle_interpret_content().

◆ SESSION_BUCKETS

#define SESSION_BUCKETS   37

Number of buckets for sessions, on a per-endpoint basis.

Definition at line 229 of file chan_motif.c.

Referenced by jingle_endpoint_state_create().

◆ XMPP_STANZAS_NS

#define XMPP_STANZAS_NS   "urn:ietf:params:xml:ns:xmpp-stanzas"

Namespace for XMPP stanzas.

Definition at line 259 of file chan_motif.c.

Referenced by jingle_outgoing_hook().

Enumeration Type Documentation

◆ jingle_transport

The various transport methods supported, from highest priority to lowest priority when doing fallback.

Enumerator
JINGLE_TRANSPORT_ICE_UDP 

XEP-0176

JINGLE_TRANSPORT_GOOGLE_V2 

https://developers.google.com/talk/call_signaling

JINGLE_TRANSPORT_GOOGLE_V1 

Undocumented initial Google specification

JINGLE_TRANSPORT_NONE 

No transport specified

Definition at line 262 of file chan_motif.c.

262  {
263  JINGLE_TRANSPORT_ICE_UDP = 3, /*!< XEP-0176 */
264  JINGLE_TRANSPORT_GOOGLE_V2 = 2, /*!< https://developers.google.com/talk/call_signaling */
265  JINGLE_TRANSPORT_GOOGLE_V1 = 1, /*!< Undocumented initial Google specification */
266  JINGLE_TRANSPORT_NONE = 0, /*!< No transport specified */
267 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2830 of file chan_motif.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2830 of file chan_motif.c.

◆ 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 2830 of file chan_motif.c.

◆ CONFIG_INFO_STANDARD()

CONFIG_INFO_STANDARD ( cfg_info  ,
globals  ,
jingle_config_alloc  ,
files = ACO_FILES(&jingle_conf) 
)

Referenced by jingle_config_alloc().

◆ custom_connection_handler()

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

Custom handler for connection.

Definition at line 2674 of file chan_motif.c.

References ast_log, ast_xmpp_client_find(), jingle_endpoint::connection, ast_xmpp_client::filter, GOOGLE_SESSION_NS, jingle_action_hook(), JINGLE_NS, LOG_ERROR, jingle_endpoint::name, jingle_endpoint::rule, and ast_variable::value.

Referenced by load_module().

2675 {
2676  struct jingle_endpoint *endpoint = obj;
2677 
2678  /* You might think... but Josh, shouldn't you do this in a prelink callback? Well I *could* but until the original is destroyed
2679  * this will not actually get called, so even if the config turns out to be bogus this is harmless.
2680  */
2681  if (!(endpoint->connection = ast_xmpp_client_find(var->value))) {
2682  ast_log(LOG_ERROR, "Connection '%s' configured on endpoint '%s' could not be found\n", var->value, endpoint->name);
2683  return -1;
2684  }
2685 
2686  if (!(endpoint->rule = iks_filter_add_rule(endpoint->connection->filter, jingle_action_hook, endpoint,
2687  IKS_RULE_TYPE, IKS_PAK_IQ,
2688  IKS_RULE_NS, JINGLE_NS,
2689  IKS_RULE_NS, GOOGLE_SESSION_NS,
2690  IKS_RULE_DONE))) {
2691  ast_log(LOG_ERROR, "Action hook could not be added to connection '%s' on endpoint '%s'\n", var->value, endpoint->name);
2692  return -1;
2693  }
2694 
2695  return 0;
2696 }
static int jingle_action_hook(void *data, ikspak *pak)
Callback for when a Jingle action is received from an endpoint.
Definition: chan_motif.c:2595
const ast_string_field name
Definition: chan_motif.c:283
#define ast_log
Definition: astobj2.c:42
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
#define LOG_ERROR
Definition: logger.h:285
iksfilter * filter
Definition: xmpp.h:128
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
struct ast_xmpp_client * ast_xmpp_client_find(const char *name)
Find an XMPP client connection using a given name.
Definition: res_xmpp.c:872
#define GOOGLE_SESSION_NS
Namespace for Google Session.
Definition: chan_motif.c:250
iksrule * rule
Definition: chan_motif.c:285
#define JINGLE_NS
Namespace for Jingle itself.
Definition: chan_motif.c:232

◆ custom_group_handler()

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

Custom handler for groups.

Definition at line 2658 of file chan_motif.c.

References ast_get_group(), jingle_endpoint::callgroup, ast_variable::name, jingle_endpoint::pickupgroup, and ast_variable::value.

Referenced by load_module().

2659 {
2660  struct jingle_endpoint *endpoint = obj;
2661 
2662  if (!strcasecmp(var->name, "callgroup")) {
2663  endpoint->callgroup = ast_get_group(var->value);
2664  } else if (!strcasecmp(var->name, "pickupgroup")) {
2665  endpoint->pickupgroup = ast_get_group(var->value);
2666  } else {
2667  return -1;
2668  }
2669 
2670  return 0;
2671 }
ast_group_t pickupgroup
Definition: chan_motif.c:290
ast_group_t callgroup
Definition: chan_motif.c:289
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7557
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275

◆ custom_transport_handler()

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

Custom handler for transport.

Definition at line 2699 of file chan_motif.c.

References ast_log, JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, JINGLE_TRANSPORT_ICE_UDP, LOG_WARNING, jingle_endpoint::name, jingle_endpoint::transport, and ast_variable::value.

Referenced by load_module().

2700 {
2701  struct jingle_endpoint *endpoint = obj;
2702 
2703  if (!strcasecmp(var->value, "ice-udp")) {
2704  endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
2705  } else if (!strcasecmp(var->value, "google")) {
2707  } else if (!strcasecmp(var->value, "google-v1")) {
2709  } else {
2710  ast_log(LOG_WARNING, "Unknown transport type '%s' on endpoint '%s', defaulting to 'ice-udp'\n", var->value, endpoint->name);
2711  endpoint->transport = JINGLE_TRANSPORT_ICE_UDP;
2712  }
2713 
2714  return 0;
2715 }
#define LOG_WARNING
Definition: logger.h:274
const ast_string_field name
Definition: chan_motif.c:283
#define ast_log
Definition: astobj2.c:42
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
enum jingle_transport transport
Definition: chan_motif.c:291

◆ jingle_action_hook()

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

Callback for when a Jingle action is received from an endpoint.

Definition at line 2595 of file chan_motif.c.

References ao2_find, ao2_ref, ARRAY_LEN, ast_callid_threadassoc_add(), ast_callid_threadassoc_remove(), ast_log, ast_strlen_zero, jingle_session::callid, jingle_action_handler::handler, jingle_action_handlers, LOG_NOTICE, NULL, OBJ_KEY, session, jingle_endpoint_state::sessions, and jingle_endpoint::state.

Referenced by custom_connection_handler().

2596 {
2597  char *action;
2598  const char *sid = NULL;
2599  struct jingle_session *session = NULL;
2600  struct jingle_endpoint *endpoint = data;
2601  int i, handled = 0;
2602 
2603  /* We accept both Jingle and Google-V1 */
2604  if (!(action = iks_find_attrib(pak->query, "action")) &&
2605  !(action = iks_find_attrib(pak->query, "type"))) {
2606  /* This occurs if either receive a packet masquerading as Jingle or Google-V1 that is actually not OR we receive a response
2607  * to a message that has no response hook. */
2608  return IKS_FILTER_EAT;
2609  }
2610 
2611  /* Bump the endpoint reference count up in case a reload occurs. Unfortunately the available synchronization between iksemel and us
2612  * does not permit us to make this completely safe. */
2613  ao2_ref(endpoint, +1);
2614 
2615  /* If a Jingle session identifier is present use it */
2616  if (!(sid = iks_find_attrib(pak->query, "sid"))) {
2617  /* If a Google-V1 session identifier is present use it */
2618  sid = iks_find_attrib(pak->query, "id");
2619  }
2620 
2621  /* If a session identifier was present in the message attempt to find the session, it is up to the action handler whether
2622  * this is required or not */
2623  if (!ast_strlen_zero(sid)) {
2624  session = ao2_find(endpoint->state->sessions, sid, OBJ_KEY);
2625  }
2626 
2627  /* If a session is present associate the callid with this thread */
2628  if (session) {
2630  }
2631 
2632  /* Iterate through supported action handlers looking for one that is able to handle this */
2633  for (i = 0; i < ARRAY_LEN(jingle_action_handlers); i++) {
2634  if (!strcasecmp(jingle_action_handlers[i].action, action)) {
2635  jingle_action_handlers[i].handler(endpoint, session, pak);
2636  handled = 1;
2637  break;
2638  }
2639  }
2640 
2641  /* If no action handler is present for the action they sent us make it evident */
2642  if (!handled) {
2643  ast_log(LOG_NOTICE, "Received action '%s' for session '%s' that has no handler\n", action, sid);
2644  }
2645 
2646  /* If a session was successfully found for this message deref it now since the handler is done */
2647  if (session) {
2649  ao2_ref(session, -1);
2650  }
2651 
2652  ao2_ref(endpoint, -1);
2653 
2654  return IKS_FILTER_EAT;
2655 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define OBJ_KEY
Definition: astobj2.h:1155
ast_callid callid
Definition: chan_motif.c:318
struct jingle_endpoint_state * state
Definition: chan_motif.c:292
#define NULL
Definition: resample.c:96
Session which contains information about an active session.
Definition: chan_motif.c:296
void(* handler)(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
Definition: chan_motif.c:375
static const struct jingle_action_handler jingle_action_handlers[]
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:1911
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:1892
#define ast_log
Definition: astobj2.c:42
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
#define LOG_NOTICE
Definition: logger.h:263
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ao2_container * sessions
Definition: chan_motif.c:271

◆ jingle_action_session_accept()

static void jingle_action_session_accept ( struct jingle_endpoint endpoint,
struct jingle_session session,
ikspak *  pak 
)
static

Handler function for the 'session-accept' action.

Definition at line 2474 of file chan_motif.c.

References ao2_unlock, ast_channel_unlock, ast_channel_unref, AST_CONTROL_ANSWER, ast_queue_control(), jingle_endpoint::connection, jingle_interpret_content(), jingle_send_error_response(), jingle_send_response(), and jingle_session_lock_full().

2475 {
2476  struct ast_channel *chan;
2477 
2478  if (!session) {
2479  jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2480  "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2481  return;
2482  }
2483 
2484 
2485  jingle_interpret_content(session, pak);
2486 
2487  if ((chan = jingle_session_lock_full(session))) {
2489  ast_channel_unlock(chan);
2490  ast_channel_unref(chan);
2491  }
2492  ao2_unlock(session);
2493 
2494  jingle_send_response(endpoint->connection, pak);
2495 }
Main Channel structure associated with a channel.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1227
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:864
#define ao2_unlock(a)
Definition: astobj2.h:730
static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
Helper function which locates content stanzas and interprets them.
Definition: chan_motif.c:2279
#define ast_channel_unlock(chan)
Definition: channel.h:2838
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
Internal helper function which sends an error response.
Definition: chan_motif.c:884
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148

◆ jingle_action_session_info()

static void jingle_action_session_info ( struct jingle_endpoint endpoint,
struct jingle_session session,
ikspak *  pak 
)
static

Handler function for the 'session-info' action.

Definition at line 2498 of file chan_motif.c.

References ao2_unlock, ast_channel_unlock, ast_channel_unref, AST_CONTROL_RINGING, ast_queue_control(), ast_queue_hold(), ast_queue_unhold(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, jingle_endpoint::connection, JINGLE_RTP_INFO_NS, jingle_send_error_response(), jingle_send_response(), jingle_session_lock_full(), and NULL.

2499 {
2500  struct ast_channel *chan;
2501 
2502  if (!session) {
2503  jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2504  "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2505  return;
2506  }
2507 
2508  if (!(chan = jingle_session_lock_full(session))) {
2509  ao2_unlock(session);
2510  jingle_send_response(endpoint->connection, pak);
2511  return;
2512  }
2513 
2514  if (iks_find_with_attrib(pak->query, "ringing", "xmlns", JINGLE_RTP_INFO_NS)) {
2516  if (ast_channel_state(chan) != AST_STATE_UP) {
2518  }
2519  } else if (iks_find_with_attrib(pak->query, "hold", "xmlns", JINGLE_RTP_INFO_NS)) {
2520  ast_queue_hold(chan, NULL);
2521  } else if (iks_find_with_attrib(pak->query, "unhold", "xmlns", JINGLE_RTP_INFO_NS)) {
2522  ast_queue_unhold(chan);
2523  }
2524 
2525  ast_channel_unlock(chan);
2526  ast_channel_unref(chan);
2527  ao2_unlock(session);
2528 
2529  jingle_send_response(endpoint->connection, pak);
2530 }
Main Channel structure associated with a channel.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1227
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1212
static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:864
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define JINGLE_RTP_INFO_NS
Namespace for Jingle RTP info.
Definition: chan_motif.c:238
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1187
#define ast_channel_unlock(chan)
Definition: channel.h:2838
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
Internal helper function which sends an error response.
Definition: chan_motif.c:884
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7325

◆ jingle_action_session_initiate()

static void jingle_action_session_initiate ( struct jingle_endpoint endpoint,
struct jingle_session session,
ikspak *  pak 
)
static

Action handlers.

Handler function for the 'session-initiate' action.

Definition at line 2390 of file chan_motif.c.

References ao2_link, ao2_ref, ast_channel_lock, ast_channel_unlock, ast_hangup(), ast_log, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, jingle_endpoint::connection, jingle_session::gone, jingle_alloc(), jingle_interpret_content(), jingle_new(), jingle_send_error_response(), jingle_send_response(), jingle_send_transport_info(), JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_NONE, LOG_WARNING, NULL, jingle_endpoint_state::sessions, jingle_endpoint::state, and jingle_session::transport.

2391 {
2392  char *sid;
2393  enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
2394  struct ast_channel *chan;
2395  int res;
2396 
2397  if (session) {
2398  /* This is a duplicate session setup, so respond accordingly */
2399  jingle_send_error_response(endpoint->connection, pak, "result", "out-of-order", NULL);
2400  return;
2401  }
2402 
2403  /* Retrieve the session identifier from the message, note that this may alter the transport */
2404  if ((sid = iks_find_attrib(pak->query, "id"))) {
2405  /* The presence of the session identifier in the 'id' attribute tells us that this is Google-V1 as everything else uses 'sid' */
2406  transport = JINGLE_TRANSPORT_GOOGLE_V1;
2407  } else if (!(sid = iks_find_attrib(pak->query, "sid"))) {
2408  jingle_send_error_response(endpoint->connection, pak, "bad-request", NULL, NULL);
2409  return;
2410  }
2411 
2412  /* Create a new local session */
2413  if (!(session = jingle_alloc(endpoint, pak->from->full, sid))) {
2414  jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2415  return;
2416  }
2417 
2418  /* If we determined that the transport should change as a result of how we got the SID change it */
2419  if (transport != JINGLE_TRANSPORT_NONE) {
2420  session->transport = transport;
2421  }
2422 
2423  /* Create a new Asterisk channel using the above local session */
2424  if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, pak->from->user, NULL, NULL, pak->from->full))) {
2425  ao2_ref(session, -1);
2426  jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2427  return;
2428  }
2429 
2430  ao2_link(endpoint->state->sessions, session);
2431 
2432  ast_channel_lock(chan);
2434  ast_channel_unlock(chan);
2435  res = ast_pbx_start(chan);
2436 
2437  switch (res) {
2438  case AST_PBX_FAILED:
2439  ast_log(LOG_WARNING, "Failed to start PBX :(\n");
2440  jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2441  session->gone = 1;
2442  ast_hangup(chan);
2443  break;
2444  case AST_PBX_CALL_LIMIT:
2445  ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
2446  jingle_send_error_response(endpoint->connection, pak, "wait", "resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2447  ast_hangup(chan);
2448  break;
2449  case AST_PBX_SUCCESS:
2450  jingle_send_response(endpoint->connection, pak);
2451 
2452  /* Only send a transport-info message if we successfully interpreted the available content */
2453  if (!jingle_interpret_content(session, pak)) {
2454  jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
2455  }
2456  break;
2457  }
2458 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
Main Channel structure associated with a channel.
static struct jingle_session * jingle_alloc(struct jingle_endpoint *endpoint, const char *from, const char *sid)
Internal helper function used to allocate Jingle session on an endpoint.
Definition: chan_motif.c:701
static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:864
#define LOG_WARNING
Definition: logger.h:274
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4703
struct jingle_endpoint_state * state
Definition: chan_motif.c:292
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
jingle_transport
The various transport methods supported, from highest priority to lowest priority when doing fallback...
Definition: chan_motif.c:262
static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
Helper function which locates content stanzas and interprets them.
Definition: chan_motif.c:2279
#define ast_channel_unlock(chan)
Definition: channel.h:2838
unsigned int gone
Definition: chan_motif.c:317
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2523
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
Internal helper function which sends an error response.
Definition: chan_motif.c:884
enum jingle_transport transport
Definition: chan_motif.c:304
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7325
static void jingle_send_transport_info(struct jingle_session *session, const char *from)
Internal function which sends a transport-info message.
Definition: chan_motif.c:1211
static struct ast_channel * jingle_new(struct jingle_endpoint *endpoint, struct jingle_session *session, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
Function called to create a new Jingle Asterisk channel.
Definition: chan_motif.c:768
struct ao2_container * sessions
Definition: chan_motif.c:271
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ jingle_action_session_terminate()

static void jingle_action_session_terminate ( struct jingle_endpoint endpoint,
struct jingle_session session,
ikspak *  pak 
)
static

Handler function for the 'session-terminate' action.

Definition at line 2533 of file chan_motif.c.

References ao2_unlock, ARRAY_LEN, ast_alloca, ast_control_pvt_cause_code::ast_cause, AST_CAUSE_NORMAL, ast_channel_hangupcause_hash_set(), AST_CHANNEL_NAME, ast_channel_name(), ast_channel_unlock, ast_channel_unref, AST_CONTROL_PVT_CAUSE_CODE, ast_copy_string(), ast_debug, ast_queue_control_data(), ast_queue_hangup_with_cause(), jingle_reason_mapping::cause, ast_control_pvt_cause_code::chan_name, ast_control_pvt_cause_code::code, jingle_endpoint::connection, jingle_session::gone, jingle_reason_mappings, jingle_send_error_response(), jingle_send_response(), jingle_session_lock_full(), and text.

2534 {
2535  struct ast_channel *chan;
2536  iks *reason, *text;
2537  int cause = AST_CAUSE_NORMAL;
2538  struct ast_control_pvt_cause_code *cause_code;
2539  int data_size = sizeof(*cause_code);
2540 
2541  if (!session) {
2542  jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2543  "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2544  return;
2545  }
2546 
2547  if (!(chan = jingle_session_lock_full(session))) {
2548  ao2_unlock(session);
2549  jingle_send_response(endpoint->connection, pak);
2550  return;
2551  }
2552 
2553  /* Pull the reason text from the session-terminate message and translate it into a cause code */
2554  if ((reason = iks_find(pak->query, "reason")) && (text = iks_child(reason))) {
2555  int i;
2556 
2557  /* Size of the string making up the cause code is "Motif " + text */
2558  data_size += 6 + strlen(iks_name(text));
2559  cause_code = ast_alloca(data_size);
2560  memset(cause_code, 0, data_size);
2561 
2562  /* Get the appropriate cause code mapping for this reason */
2563  for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
2564  if (!strcasecmp(jingle_reason_mappings[i].reason, iks_name(text))) {
2565  cause = jingle_reason_mappings[i].cause;
2566  break;
2567  }
2568  }
2569 
2570  /* Store the technology specific information */
2571  snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "Motif %s", iks_name(text));
2572  } else {
2573  /* No technology specific information is available */
2574  cause_code = ast_alloca(data_size);
2575  memset(cause_code, 0, data_size);
2576  }
2577 
2579  cause_code->ast_cause = cause;
2580  ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
2581  ast_channel_hangupcause_hash_set(chan, cause_code, data_size);
2582 
2583  ast_debug(3, "Hanging up channel '%s' due to session terminate message with cause '%d'\n", ast_channel_name(chan), cause);
2584  ast_queue_hangup_with_cause(chan, cause);
2585  session->gone = 1;
2586 
2587  ast_channel_unlock(chan);
2588  ast_channel_unref(chan);
2589  ao2_unlock(session);
2590 
2591  jingle_send_response(endpoint->connection, pak);
2592 }
Main Channel structure associated with a channel.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char chan_name[AST_CHANNEL_NAME]
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:864
#define ao2_unlock(a)
Definition: astobj2.h:730
char * text
Definition: app_queue.c:1511
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1162
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define AST_CAUSE_NORMAL
Definition: causes.h:150
static const struct jingle_reason_mapping jingle_reason_mappings[]
#define ast_channel_unlock(chan)
Definition: channel.h:2838
unsigned int gone
Definition: chan_motif.c:317
#define AST_CHANNEL_NAME
Definition: channel.h:172
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
Internal helper function which sends an error response.
Definition: chan_motif.c:884
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1234
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel. ...
Definition: channel.c:4340

◆ jingle_action_transport_info()

static void jingle_action_transport_info ( struct jingle_endpoint endpoint,
struct jingle_session session,
ikspak *  pak 
)
static

Handler function for the 'transport-info' action.

Definition at line 2461 of file chan_motif.c.

References jingle_endpoint::connection, jingle_interpret_content(), jingle_send_error_response(), and jingle_send_response().

2462 {
2463  if (!session) {
2464  jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2465  "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2466  return;
2467  }
2468 
2469  jingle_interpret_content(session, pak);
2470  jingle_send_response(endpoint->connection, pak);
2471 }
static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:864
static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
Helper function which locates content stanzas and interprets them.
Definition: chan_motif.c:2279
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
static void jingle_send_error_response(struct ast_xmpp_client *connection, ikspak *pak, const char *type, const char *reasonstr, const char *reasonstr2)
Internal helper function which sends an error response.
Definition: chan_motif.c:884

◆ jingle_add_content()

static int jingle_add_content ( struct jingle_session session,
iks *  jingle,
iks *  content,
iks *  description,
iks *  transport,
const char *  name,
enum ast_media_type  type,
struct ast_rtp_instance rtp,
iks **  payloads 
)
static

Helper function which adds content to a description.

Definition at line 1392 of file chan_motif.c.

References AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, GOOGLE_PHONE_NS, GOOGLE_TRANSPORT_NS, jingle_add_payloads_to_description(), JINGLE_ICE_UDP_NS, JINGLE_RTP_NS, JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, JINGLE_TRANSPORT_ICE_UDP, jingle_session::outgoing, and jingle_session::transport.

Referenced by jingle_send_session_action().

1394 {
1395  int res = 0;
1396 
1397  if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
1398  iks_insert_attrib(content, "creator", session->outgoing ? "initiator" : "responder");
1399  iks_insert_attrib(content, "name", name);
1400  iks_insert_node(jingle, content);
1401 
1402  iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS);
1403  if (type == AST_MEDIA_TYPE_AUDIO) {
1404  iks_insert_attrib(description, "media", "audio");
1405  } else if (type == AST_MEDIA_TYPE_VIDEO) {
1406  iks_insert_attrib(description, "media", "video");
1407  } else {
1408  return -1;
1409  }
1410  iks_insert_node(content, description);
1411  } else {
1412  iks_insert_attrib(description, "xmlns", GOOGLE_PHONE_NS);
1413  iks_insert_node(jingle, description);
1414  }
1415 
1416  if (!(res = jingle_add_payloads_to_description(session, rtp, description, payloads, type))) {
1417  if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1418  iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
1419  iks_insert_node(content, transport);
1420  } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1421  iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
1422  iks_insert_node(content, transport);
1423  }
1424  }
1425 
1426  return res;
1427 }
static const char type[]
Definition: chan_ooh323.c:109
#define GOOGLE_TRANSPORT_NS
Namespace for Google Talk ICE-UDP.
Definition: chan_motif.c:244
#define GOOGLE_PHONE_NS
Namespace for Google Phone description.
Definition: chan_motif.c:253
unsigned int outgoing
Definition: chan_motif.c:316
#define JINGLE_RTP_NS
Namespace for Jingle RTP sessions.
Definition: chan_motif.c:235
static const char name[]
Definition: cdr_mysql.c:74
static int jingle_add_payloads_to_description(struct jingle_session *session, struct ast_rtp_instance *rtp, iks *description, iks **payloads, enum ast_media_type type)
Internal helper function which adds payloads to a description.
Definition: chan_motif.c:1306
enum jingle_transport transport
Definition: chan_motif.c:304
#define JINGLE_ICE_UDP_NS
Namespace for Jingle ICE-UDP.
Definition: chan_motif.c:241

◆ jingle_add_google_candidates_to_transport()

static int jingle_add_google_candidates_to_transport ( struct ast_rtp_instance rtp,
iks *  transport,
iks **  candidates,
unsigned int  video,
enum jingle_transport  transport_type,
unsigned int  maximum 
)
static

Internal helper function which adds Google candidates to a transport node.

Definition at line 980 of file chan_motif.c.

References ast_rtp_engine_ice_candidate::address, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log, AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, ast_rtp_instance_get_ice(), ast_sockaddr_stringify_host(), ast_sockaddr_stringify_port(), ast_rtp_engine_ice::get_local_candidates, ast_rtp_engine_ice::get_password, ast_rtp_engine_ice::get_ufrag, GOOGLE_TRANSPORT_NS, ast_rtp_engine_ice_candidate::id, JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, and ast_rtp_engine_ice_candidate::type.

Referenced by jingle_send_transport_info().

981 {
982  struct ast_rtp_engine_ice *ice;
983  struct ao2_container *local_candidates;
984  struct ao2_iterator it;
985  struct ast_rtp_engine_ice_candidate *candidate;
986  int i = 0, res = 0;
987 
988  if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
989  ast_log(LOG_ERROR, "Unable to add Google ICE candidates as ICE support not available or no candidates available\n");
990  return -1;
991  }
992 
993  if (transport_type != JINGLE_TRANSPORT_GOOGLE_V1) {
994  iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
995  }
996 
997  it = ao2_iterator_init(local_candidates, 0);
998 
999  while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
1000  iks *local_candidate;
1001  /* In Google land a username is 16 bytes, explicitly */
1002  char ufrag[17] = "";
1003 
1004  if (!(local_candidate = iks_new("candidate"))) {
1005  res = -1;
1006  ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for Google ICE transport\n");
1007  break;
1008  }
1009 
1010  if (candidate->id == 1) {
1011  iks_insert_attrib(local_candidate, "name", !video ? "rtp" : "video_rtp");
1012  } else if (candidate->id == 2) {
1013  iks_insert_attrib(local_candidate, "name", !video ? "rtcp" : "video_rtcp");
1014  } else {
1015  iks_delete(local_candidate);
1016  continue;
1017  }
1018 
1019  iks_insert_attrib(local_candidate, "address", ast_sockaddr_stringify_host(&candidate->address));
1020  iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
1021 
1022  if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
1023  iks_insert_attrib(local_candidate, "preference", "0.95");
1024  iks_insert_attrib(local_candidate, "type", "local");
1025  } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
1026  iks_insert_attrib(local_candidate, "preference", "0.9");
1027  iks_insert_attrib(local_candidate, "type", "stun");
1028  }
1029 
1030  iks_insert_attrib(local_candidate, "protocol", "udp");
1031  iks_insert_attrib(local_candidate, "network", "0");
1032  snprintf(ufrag, sizeof(ufrag), "%s", ice->get_ufrag(rtp));
1033  iks_insert_attrib(local_candidate, "username", ufrag);
1034  iks_insert_attrib(local_candidate, "generation", "0");
1035 
1036  if (transport_type == JINGLE_TRANSPORT_GOOGLE_V1) {
1037  iks_insert_attrib(local_candidate, "password", "");
1038  iks_insert_attrib(local_candidate, "foundation", "0");
1039  iks_insert_attrib(local_candidate, "component", "1");
1040  } else {
1041  iks_insert_attrib(local_candidate, "password", ice->get_password(rtp));
1042  }
1043 
1044  /* You may notice a lack of relay support up above - this is because we don't support it for use with
1045  * the Google talk transport due to their arcane support. */
1046 
1047  iks_insert_node(transport, local_candidate);
1048  candidates[i++] = local_candidate;
1049  }
1050 
1051  ao2_iterator_destroy(&it);
1052  ao2_ref(local_candidates, -1);
1053 
1054  return res;
1055 }
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:496
#define GOOGLE_TRANSPORT_NS
Namespace for Google Talk ICE-UDP.
Definition: chan_motif.c:244
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Structure for an ICE candidate.
Definition: rtp_engine.h:473
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:480
static char * ast_sockaddr_stringify_port(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return a port only.
Definition: netsock2.h:362
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:494
#define LOG_ERROR
Definition: logger.h:285
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:498
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:475
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
struct ast_sockaddr address
Definition: rtp_engine.h:478
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331

◆ jingle_add_ice_udp_candidates_to_transport()

static int jingle_add_ice_udp_candidates_to_transport ( struct ast_rtp_instance rtp,
iks *  transport,
iks **  candidates,
unsigned int  maximum 
)
static

Internal helper function which adds ICE-UDP candidates to a transport node.

Definition at line 918 of file chan_motif.c.

References ast_rtp_engine_ice_candidate::address, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log, ast_random(), AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, ast_rtp_instance_get_ice(), ast_sockaddr_stringify_host(), ast_sockaddr_stringify_port(), ast_str_hash(), ast_rtp_engine_ice_candidate::foundation, ast_rtp_engine_ice::get_local_candidates, ast_rtp_engine_ice::get_password, ast_rtp_engine_ice::get_ufrag, ast_rtp_engine_ice_candidate::id, JINGLE_ICE_UDP_NS, LOG_ERROR, ast_rtp_engine_ice_candidate::priority, tmp(), and ast_rtp_engine_ice_candidate::type.

Referenced by jingle_send_transport_info().

919 {
920  struct ast_rtp_engine_ice *ice;
921  struct ao2_container *local_candidates;
922  struct ao2_iterator it;
923  struct ast_rtp_engine_ice_candidate *candidate;
924  int i = 0, res = 0;
925 
926  if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
927  ast_log(LOG_ERROR, "Unable to add ICE-UDP candidates as ICE support not available or no candidates available\n");
928  return -1;
929  }
930 
931  iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
932  iks_insert_attrib(transport, "pwd", ice->get_password(rtp));
933  iks_insert_attrib(transport, "ufrag", ice->get_ufrag(rtp));
934 
935  it = ao2_iterator_init(local_candidates, 0);
936 
937  while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
938  iks *local_candidate;
939  char tmp[30];
940 
941  if (!(local_candidate = iks_new("candidate"))) {
942  res = -1;
943  ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for ICE-UDP transport\n");
944  break;
945  }
946 
947  snprintf(tmp, sizeof(tmp), "%u", candidate->id);
948  iks_insert_attrib(local_candidate, "component", tmp);
949  snprintf(tmp, sizeof(tmp), "%d", ast_str_hash(candidate->foundation));
950  iks_insert_attrib(local_candidate, "foundation", tmp);
951  iks_insert_attrib(local_candidate, "generation", "0");
952  iks_insert_attrib(local_candidate, "network", "0");
953  snprintf(tmp, sizeof(tmp), "%04lx", (unsigned long)(ast_random() & 0xffff));
954  iks_insert_attrib(local_candidate, "id", tmp);
955  iks_insert_attrib(local_candidate, "ip", ast_sockaddr_stringify_host(&candidate->address));
956  iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
957  snprintf(tmp, sizeof(tmp), "%d", candidate->priority);
958  iks_insert_attrib(local_candidate, "priority", tmp);
959  iks_insert_attrib(local_candidate, "protocol", "udp");
960 
961  if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
962  iks_insert_attrib(local_candidate, "type", "host");
963  } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
964  iks_insert_attrib(local_candidate, "type", "srflx");
965  } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_RELAYED) {
966  iks_insert_attrib(local_candidate, "type", "relay");
967  }
968 
969  iks_insert_node(transport, local_candidate);
970  candidates[i++] = local_candidate;
971  }
972 
974  ao2_ref(local_candidates, -1);
975 
976  return res;
977 }
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:496
static int tmp()
Definition: bt_open.c:389
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Structure for an ICE candidate.
Definition: rtp_engine.h:473
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:480
static char * ast_sockaddr_stringify_port(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return a port only.
Definition: netsock2.h:362
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
long int ast_random(void)
Definition: main/utils.c:1935
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:494
#define LOG_ERROR
Definition: logger.h:285
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:498
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:475
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define JINGLE_ICE_UDP_NS
Namespace for Jingle ICE-UDP.
Definition: chan_motif.c:241
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
struct ast_sockaddr address
Definition: rtp_engine.h:478
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:331
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ jingle_add_payloads_to_description()

static int jingle_add_payloads_to_description ( struct jingle_session session,
struct ast_rtp_instance rtp,
iks *  description,
iks **  payloads,
enum ast_media_type  type 
)
static

Internal helper function which adds payloads to a description.

Definition at line 1306 of file chan_motif.c.

References ao2_ref, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_g722, ast_format_get_type(), AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), format, GOOGLE_PHONE_NS, JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, jingle_session::jointcap, jingle_session::maxpayloads, tmp(), jingle_session::transport, and ast_channel::x.

Referenced by jingle_add_content().

1307 {
1308  int x = 0, i = 0, res = 0;
1309 
1310  for (x = 0; (x < ast_format_cap_count(session->jointcap)) && (i < (session->maxpayloads - 2)); x++) {
1311  struct ast_format *format = ast_format_cap_get_format(session->jointcap, x);
1312  int rtp_code;
1313  iks *payload;
1314  char tmp[32];
1315 
1316  if (ast_format_get_type(format) != type) {
1317  ao2_ref(format, -1);
1318  continue;
1319  }
1320 
1321  if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, format, 0)) == -1) ||
1322  (!(payload = iks_new("payload-type")))) {
1323  ao2_ref(format, -1);
1324  return -1;
1325  }
1326 
1327  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1328  iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
1329  }
1330 
1331  snprintf(tmp, sizeof(tmp), "%d", rtp_code);
1332  iks_insert_attrib(payload, "id", tmp);
1333  iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
1334  iks_insert_attrib(payload, "channels", "1");
1335 
1337  ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
1338  iks_insert_attrib(payload, "clockrate", "16000");
1339  } else {
1340  snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, format, 0));
1341  iks_insert_attrib(payload, "clockrate", tmp);
1342  }
1343 
1344  if ((type == AST_MEDIA_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
1345  iks *parameter;
1346 
1347  /* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */
1348  if ((parameter = iks_new("parameter"))) {
1349  iks_insert_attrib(parameter, "name", "width");
1350  iks_insert_attrib(parameter, "value", "640");
1351  iks_insert_node(payload, parameter);
1352  }
1353  if ((parameter = iks_new("parameter"))) {
1354  iks_insert_attrib(parameter, "name", "height");
1355  iks_insert_attrib(parameter, "value", "480");
1356  iks_insert_node(payload, parameter);
1357  }
1358  if ((parameter = iks_new("parameter"))) {
1359  iks_insert_attrib(parameter, "name", "framerate");
1360  iks_insert_attrib(parameter, "value", "30");
1361  iks_insert_node(payload, parameter);
1362  }
1363  }
1364 
1365  iks_insert_node(description, payload);
1366  payloads[i++] = payload;
1367 
1368  ao2_ref(format, -1);
1369  }
1370  /* If this is for audio and there is room for RFC2833 add it in */
1371  if ((type == AST_MEDIA_TYPE_AUDIO) && (i < session->maxpayloads)) {
1372  iks *payload;
1373 
1374  if ((payload = iks_new("payload-type"))) {
1375  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1376  iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
1377  }
1378 
1379  iks_insert_attrib(payload, "id", "101");
1380  iks_insert_attrib(payload, "name", "telephone-event");
1381  iks_insert_attrib(payload, "channels", "1");
1382  iks_insert_attrib(payload, "clockrate", "8000");
1383  iks_insert_node(description, payload);
1384  payloads[i++] = payload;
1385  }
1386  }
1387 
1388  return res;
1389 }
static const char type[]
Definition: chan_ooh323.c:109
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
#define GOOGLE_PHONE_NS
Namespace for Google Phone description.
Definition: chan_motif.c:253
static int tmp()
Definition: bt_open.c:389
Definition of a media format.
Definition: format.c:43
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
struct ast_format_cap * jointcap
Definition: chan_motif.c:314
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:111
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:1992
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
Retrieve a rx mapped payload type based on whether it is an Asterisk format and the code...
Definition: rtp_engine.c:1873
#define ao2_ref(o, delta)
Definition: astobj2.h:464
unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, const struct ast_format *format, int code)
Get the sample rate associated with known RTP payload types.
Definition: rtp_engine.c:2022
enum jingle_transport transport
Definition: chan_motif.c:304
unsigned int maxpayloads
Definition: chan_motif.c:306
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ jingle_alloc()

static struct jingle_session * jingle_alloc ( struct jingle_endpoint endpoint,
const char *  from,
const char *  sid 
)
static

Internal helper function used to allocate Jingle session on an endpoint.

Definition at line 701 of file chan_motif.c.

References ao2_alloc, ao2_ref, ast_copy_string(), ast_create_callid(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, AST_MEDIA_TYPE_UNKNOWN, ast_random(), ast_read_threadstorage_callid(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_RTCP, ast_sockaddr_parse(), ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strlen_zero, jingle_session::callid, jingle_endpoint::cap, jingle_session::cap, jingle_endpoint::connection, jingle_session::connection, jingle_session_destructor(), jingle_session::jointcap, jingle_endpoint::maxicecandidates, jingle_session::maxicecandidates, jingle_endpoint::maxpayloads, jingle_session::maxpayloads, NULL, jingle_session::outgoing, jingle_session::peercap, jingle_session::remote, jingle_session::remote_original, jingle_session::rtp, session, jingle_endpoint::state, jingle_session::state, jingle_endpoint::transport, and jingle_session::transport.

Referenced by jingle_action_session_initiate(), and jingle_request().

702 {
703  struct jingle_session *session;
705  struct ast_sockaddr tmp;
706 
707  if (!(session = ao2_alloc(sizeof(*session), jingle_session_destructor))) {
708  return NULL;
709  }
710 
712  session->callid = (callid ? callid : ast_create_callid());
713 
714  if (ast_string_field_init(session, 512)) {
715  ao2_ref(session, -1);
716  return NULL;
717  }
718 
719  if (!ast_strlen_zero(from)) {
720  ast_copy_string(session->remote_original, from, sizeof(session->remote_original));
721  ast_copy_string(session->remote, from, sizeof(session->remote));
722  }
723 
724  if (ast_strlen_zero(sid)) {
725  ast_string_field_build(session, sid, "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
726  session->outgoing = 1;
727  ast_string_field_set(session, audio_name, "audio");
728  ast_string_field_set(session, video_name, "video");
729  } else {
730  ast_string_field_set(session, sid, sid);
731  }
732 
733  ao2_ref(endpoint->state, +1);
734  session->state = endpoint->state;
735  ao2_ref(endpoint->connection, +1);
736  session->connection = endpoint->connection;
737  session->transport = endpoint->transport;
738 
742  !session->callid) {
743  ao2_ref(session, -1);
744  return NULL;
745  }
746 
748 
749  /* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine
750  * that we want IPv4 */
751  ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
752 
753  /* Sessions always carry audio, but video is optional so don't enable it here */
754  if (!(session->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
755  ao2_ref(session, -1);
756  return NULL;
757  }
760 
761  session->maxicecandidates = endpoint->maxicecandidates;
762  session->maxpayloads = endpoint->maxpayloads;
763 
764  return session;
765 }
struct ast_format_cap * cap
Definition: chan_motif.c:288
unsigned int maxpayloads
Definition: chan_motif.c:287
struct jingle_endpoint_state * state
Definition: chan_motif.c:302
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
ast_callid callid
Definition: chan_motif.c:318
static int tmp()
Definition: bt_open.c:389
Definition: sched.c:76
struct jingle_endpoint_state * state
Definition: chan_motif.c:292
unsigned int ast_callid
Definition: logger.h:87
struct ast_format_cap * jointcap
Definition: chan_motif.c:314
#define NULL
Definition: resample.c:96
Session which contains information about an active session.
Definition: chan_motif.c:296
Socket address structure.
Definition: netsock2.h:97
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:1870
unsigned int outgoing
Definition: chan_motif.c:316
struct ast_format_cap * cap
Definition: chan_motif.c:313
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
long int ast_random(void)
Definition: main/utils.c:1935
unsigned int maxicecandidates
Definition: chan_motif.c:305
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:1865
char remote_original[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:307
struct ast_xmpp_client * connection
Definition: chan_motif.c:303
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_strlen_zero(a)
Definition: muted.c:73
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
char remote[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:308
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:550
static void jingle_session_destructor(void *obj)
Destructor for Jingle sessions.
Definition: chan_motif.c:561
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
enum jingle_transport transport
Definition: chan_motif.c:304
unsigned int maxpayloads
Definition: chan_motif.c:306
struct ast_format_cap * peercap
Definition: chan_motif.c:315
enum jingle_transport transport
Definition: chan_motif.c:291
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:705
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:465
unsigned int maxicecandidates
Definition: chan_motif.c:286
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ jingle_answer()

static int jingle_answer ( struct ast_channel ast)
static

Function called by core when we should answer a Jingle session.

Definition at line 1625 of file chan_motif.c.

References ast_channel_tech_pvt(), AST_STATE_UP, jingle_send_session_accept(), and session.

1626 {
1628 
1629  /* The channel has already been answered so we don't need to do anything */
1630  if (ast_channel_state(ast) == AST_STATE_UP) {
1631  return 0;
1632  }
1633 
1634  jingle_send_session_accept(session);
1635 
1636  return 0;
1637 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
Session which contains information about an active session.
Definition: chan_motif.c:296
static void jingle_send_session_accept(struct jingle_session *session)
Internal function which sends a session-accept message.
Definition: chan_motif.c:1518
static struct ast_mansession session

◆ jingle_call()

static int jingle_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
)
static

Function called by core to actually start calling a remote party.

Definition at line 1850 of file chan_motif.c.

References ast_channel_tech_pvt(), ast_format_cap_append_from_cap(), AST_MEDIA_TYPE_UNKNOWN, ast_setstate(), AST_STATE_RING, jingle_session::cap, jingle_session::connection, ast_xmpp_client::filter, jingle_outgoing_hook(), jingle_send_session_initiate(), jingle_session::jointcap, ast_xmpp_client::mid, jingle_session::rule, and session.

1851 {
1853 
1855 
1856  /* Since we have no idea of the remote capabilities use ours for now */
1858 
1859  /* We set up a hook so we can know when our session-initiate message was accepted or rejected */
1860  session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1861  IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1862 
1864 
1865  return 0;
1866 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_format_cap * jointcap
Definition: chan_motif.c:314
Session which contains information about an active session.
Definition: chan_motif.c:296
struct ast_format_cap * cap
Definition: chan_motif.c:313
static struct ast_mansession session
iksfilter * filter
Definition: xmpp.h:128
static int jingle_outgoing_hook(void *data, ikspak *pak)
Callback for when a response is received for an outgoing session-initiate message.
Definition: chan_motif.c:1524
struct ast_xmpp_client * connection
Definition: chan_motif.c:303
char mid[6]
Definition: xmpp.h:125
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7325
static void jingle_send_session_initiate(struct jingle_session *session)
Internal function which sends a session-inititate message.
Definition: chan_motif.c:1512
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
iksrule * rule
Definition: chan_motif.c:309

◆ jingle_config_alloc()

static void* jingle_config_alloc ( void  )
static

Allocator called when module configuration should appear.

Definition at line 598 of file chan_motif.c.

References ACO_FILES, ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, CONFIG_INFO_STANDARD(), ENDPOINT_BUCKETS, jingle_config::endpoints, globals, jingle_config_destructor(), jingle_endpoint_cmp(), jingle_endpoint_hash(), and NULL.

599 {
600  struct jingle_config *cfg;
601 
602  if (!(cfg = ao2_alloc(sizeof(*cfg), jingle_config_destructor))) {
603  return NULL;
604  }
605 
608  if (!cfg->endpoints) {
609  ao2_ref(cfg, -1);
610  return NULL;
611  }
612 
613  return cfg;
614 }
static int jingle_endpoint_cmp(void *obj, void *arg, int flags)
Comparator function for Jingle endpoints.
Definition: chan_motif.c:535
struct ao2_container * endpoints
Definition: chan_motif.c:324
#define NULL
Definition: resample.c:96
#define ENDPOINT_BUCKETS
Number of buckets for endpoints.
Definition: chan_motif.c:226
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static int jingle_endpoint_hash(const void *obj, const int flags)
Hashing function for Jingle endpoints.
Definition: chan_motif.c:526
static void jingle_config_destructor(void *obj)
Destructor called when module configuration goes away.
Definition: chan_motif.c:591

◆ jingle_config_destructor()

static void jingle_config_destructor ( void *  obj)
static

Destructor called when module configuration goes away.

Definition at line 591 of file chan_motif.c.

References ao2_cleanup, and jingle_config::endpoints.

Referenced by jingle_config_alloc().

592 {
593  struct jingle_config *cfg = obj;
594  ao2_cleanup(cfg->endpoints);
595 }
struct ao2_container * endpoints
Definition: chan_motif.c:324
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ jingle_digit_begin()

static int jingle_digit_begin ( struct ast_channel ast,
char  digit 
)
static

Function called by core to start a DTMF digit.

Definition at line 1826 of file chan_motif.c.

References ast_channel_tech_pvt(), ast_rtp_instance_dtmf_begin(), jingle_session::rtp, and session.

1827 {
1829 
1830  if (session->rtp) {
1832  }
1833 
1834  return 0;
1835 }
char digit
void * ast_channel_tech_pvt(const struct ast_channel *chan)
Session which contains information about an active session.
Definition: chan_motif.c:296
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
static struct ast_mansession session
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
Definition: rtp_engine.c:2081

◆ jingle_digit_end()

static int jingle_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
)
static

Function called by core to stop a DTMF digit.

Definition at line 1838 of file chan_motif.c.

References ast_channel_tech_pvt(), ast_rtp_instance_dtmf_end_with_duration(), jingle_session::rtp, and session.

1839 {
1841 
1842  if (session->rtp) {
1843  ast_rtp_instance_dtmf_end_with_duration(session->rtp, digit, duration);
1844  }
1845 
1846  return 0;
1847 }
char digit
void * ast_channel_tech_pvt(const struct ast_channel *chan)
Session which contains information about an active session.
Definition: chan_motif.c:296
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
static struct ast_mansession session
int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
Definition: rtp_engine.c:2109

◆ jingle_enable_video()

static void jingle_enable_video ( struct jingle_session session)
static

Internal helper function which enables video support on a sesson if possible.

Definition at line 668 of file chan_motif.c.

References ast_channel_set_fd(), ast_channel_uniqueid(), ast_format_cap_get_framing(), ast_format_cap_has_type(), AST_MEDIA_TYPE_VIDEO, ast_rtp_codecs_set_framing(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_ice(), ast_rtp_instance_new(), ast_rtp_instance_set_channel_id(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_RTCP, ast_sockaddr_parse(), jingle_session::cap, JINGLE_TRANSPORT_GOOGLE_V2, NULL, jingle_session::owner, ast_rtp_engine_ice::stop, jingle_session::transport, and jingle_session::vrtp.

Referenced by jingle_interpret_description(), and jingle_request().

669 {
670  struct ast_sockaddr tmp;
671  struct ast_rtp_engine_ice *ice;
672 
673  /* If video is already present don't do anything */
674  if (session->vrtp) {
675  return;
676  }
677 
678  /* If there are no configured video codecs do not turn video support on, it just won't work */
680  return;
681  }
682 
683  ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
684 
685  if (!(session->vrtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
686  return;
687  }
688 
691  ast_channel_set_fd(session->owner, 2, ast_rtp_instance_fd(session->vrtp, 0));
692  ast_channel_set_fd(session->owner, 3, ast_rtp_instance_fd(session->vrtp, 1));
694  ast_format_cap_get_framing(session->cap));
695  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
696  ice->stop(session->vrtp);
697  }
698 }
unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
Get the global framing.
Definition: format_cap.c:438
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition: rtp_engine.c:553
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
static int tmp()
Definition: bt_open.c:389
Definition: sched.c:76
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
struct ast_channel * owner
Definition: chan_motif.c:310
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
Definition: rtp_engine.c:1558
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:492
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
struct ast_format_cap * cap
Definition: chan_motif.c:313
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_rtp_instance * vrtp
Definition: chan_motif.c:312
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:2192
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2406
enum jingle_transport transport
Definition: chan_motif.c:304
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:705
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:465
int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type)
Find out if the capabilities structure has any formats of a specific type.
Definition: format_cap.c:615

◆ jingle_endpoint_alloc()

static void* jingle_endpoint_alloc ( const char *  cat)
static

Allocator function for Jingle endpoints.

Definition at line 499 of file chan_motif.c.

References ao2_alloc, ao2_ref, ast_format_cap_alloc, AST_FORMAT_CAP_FLAG_DEFAULT, ast_string_field_init, ast_string_field_set, jingle_endpoint::cap, jingle_endpoint_destructor(), jingle_endpoint_state_find_or_create(), JINGLE_TRANSPORT_ICE_UDP, name, NULL, jingle_endpoint::state, and jingle_endpoint::transport.

500 {
501  struct jingle_endpoint *endpoint;
502 
503  if (!(endpoint = ao2_alloc(sizeof(*endpoint), jingle_endpoint_destructor))) {
504  return NULL;
505  }
506 
507  if (ast_string_field_init(endpoint, 512)) {
508  ao2_ref(endpoint, -1);
509  return NULL;
510  }
511 
512  if (!(endpoint->state = jingle_endpoint_state_find_or_create(cat))) {
513  ao2_ref(endpoint, -1);
514  return NULL;
515  }
516 
517  ast_string_field_set(endpoint, name, cat);
518 
521 
522  return endpoint;
523 }
static void jingle_endpoint_destructor(void *obj)
Destructor for Jingle endpoints.
Definition: chan_motif.c:441
struct ast_format_cap * cap
Definition: chan_motif.c:288
struct jingle_endpoint_state * state
Definition: chan_motif.c:292
static struct jingle_endpoint_state * jingle_endpoint_state_find_or_create(const char *category)
State find/create function.
Definition: chan_motif.c:485
#define NULL
Definition: resample.c:96
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static const char name[]
Definition: cdr_mysql.c:74
enum jingle_transport transport
Definition: chan_motif.c:291
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ jingle_endpoint_cmp()

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

Comparator function for Jingle endpoints.

Definition at line 535 of file chan_motif.c.

References CMP_MATCH, CMP_STOP, name, jingle_endpoint::name, and OBJ_KEY.

Referenced by jingle_config_alloc().

536 {
537  struct jingle_endpoint *endpoint1 = obj, *endpoint2 = arg;
538  const char *name = arg;
539 
540  return !strcmp(endpoint1->name, flags & OBJ_KEY ? name : endpoint2->name) ? CMP_MATCH | CMP_STOP : 0;
541 }
#define OBJ_KEY
Definition: astobj2.h:1155
const ast_string_field name
Definition: chan_motif.c:283
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
static const char name[]
Definition: cdr_mysql.c:74

◆ jingle_endpoint_destructor()

static void jingle_endpoint_destructor ( void *  obj)
static

Destructor for Jingle endpoints.

Definition at line 441 of file chan_motif.c.

References ao2_cleanup, ao2_ref, ast_string_field_free_memory, ast_xmpp_client_unref(), jingle_endpoint::cap, jingle_endpoint::connection, ast_xmpp_client::filter, jingle_endpoint::rule, and jingle_endpoint::state.

Referenced by jingle_endpoint_alloc().

442 {
443  struct jingle_endpoint *endpoint = obj;
444 
445  if (endpoint->rule) {
446  iks_filter_remove_rule(endpoint->connection->filter, endpoint->rule);
447  }
448 
449  if (endpoint->connection) {
451  }
452 
453  ao2_cleanup(endpoint->cap);
454  ao2_ref(endpoint->state, -1);
455 
457 }
struct ast_format_cap * cap
Definition: chan_motif.c:288
struct jingle_endpoint_state * state
Definition: chan_motif.c:292
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_xmpp_client_unref(struct ast_xmpp_client *client)
Release XMPP client connection reference.
Definition: res_xmpp.c:885
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
iksfilter * filter
Definition: xmpp.h:128
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
iksrule * rule
Definition: chan_motif.c:285

◆ jingle_endpoint_find()

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

Find function for Jingle endpoints.

Definition at line 460 of file chan_motif.c.

References ao2_find, and OBJ_KEY.

Referenced by jingle_endpoint_state_find_or_create(), and jingle_request().

461 {
462  return ao2_find(tmp_container, category, OBJ_KEY);
463 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ jingle_endpoint_hash()

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

Hashing function for Jingle endpoints.

Definition at line 526 of file chan_motif.c.

References ast_str_hash(), name, jingle_endpoint::name, and OBJ_KEY.

Referenced by jingle_config_alloc().

527 {
528  const struct jingle_endpoint *endpoint = obj;
529  const char *name = obj;
530 
531  return ast_str_hash(flags & OBJ_KEY ? name : endpoint->name);
532 }
#define OBJ_KEY
Definition: astobj2.h:1155
const ast_string_field name
Definition: chan_motif.c:283
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
static const char name[]
Definition: cdr_mysql.c:74
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ jingle_endpoint_state_create()

static struct jingle_endpoint_state* jingle_endpoint_state_create ( void  )
static

Allocator function for Jingle endpoint state.

Definition at line 466 of file chan_motif.c.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, jingle_endpoint_state_destructor(), jingle_session_cmp(), jingle_session_hash(), NULL, SESSION_BUCKETS, jingle_endpoint_state::sessions, and state.

Referenced by jingle_endpoint_state_find_or_create().

467 {
469 
470  if (!(state = ao2_alloc(sizeof(*state), jingle_endpoint_state_destructor))) {
471  return NULL;
472  }
473 
476  if (!state->sessions) {
477  ao2_ref(state, -1);
478  return NULL;
479  }
480 
481  return state;
482 }
enum sip_cc_notify_state state
Definition: chan_sip.c:956
static void jingle_endpoint_state_destructor(void *obj)
Destructor for Jingle endpoint state.
Definition: chan_motif.c:433
static int jingle_session_hash(const void *obj, const int flags)
Hashing function for Jingle sessions.
Definition: chan_motif.c:415
#define NULL
Definition: resample.c:96
static int jingle_session_cmp(void *obj, void *arg, int flags)
Comparator function for Jingle sessions.
Definition: chan_motif.c:424
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Endpoint state information.
Definition: chan_motif.c:270
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define SESSION_BUCKETS
Number of buckets for sessions, on a per-endpoint basis.
Definition: chan_motif.c:229
struct ao2_container * sessions
Definition: chan_motif.c:271

◆ jingle_endpoint_state_destructor()

static void jingle_endpoint_state_destructor ( void *  obj)
static

Destructor for Jingle endpoint state.

Definition at line 433 of file chan_motif.c.

References ao2_ref, and jingle_endpoint_state::sessions.

Referenced by jingle_endpoint_state_create().

434 {
435  struct jingle_endpoint_state *state = obj;
436 
437  ao2_ref(state->sessions, -1);
438 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Endpoint state information.
Definition: chan_motif.c:270
struct ao2_container * sessions
Definition: chan_motif.c:271

◆ jingle_endpoint_state_find_or_create()

static struct jingle_endpoint_state* jingle_endpoint_state_find_or_create ( const char *  category)
static

State find/create function.

Definition at line 485 of file chan_motif.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_ref, globals, jingle_endpoint_find(), jingle_endpoint_state_create(), NULL, and RAII_VAR.

Referenced by jingle_endpoint_alloc().

486 {
488  RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
489 
490  if (!cfg || !cfg->endpoints || !(endpoint = jingle_endpoint_find(cfg->endpoints, category))) {
492  }
493 
494  ao2_ref(endpoint->state, +1);
495  return endpoint->state;
496 }
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
#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:851
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct console_pvt globals
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
static void * jingle_endpoint_find(struct ao2_container *tmp_container, const char *category)
Find function for Jingle endpoints.
Definition: chan_motif.c:460
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct jingle_endpoint_state * jingle_endpoint_state_create(void)
Allocator function for Jingle endpoint state.
Definition: chan_motif.c:466

◆ jingle_fixup()

static int jingle_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
)
static

Function called by core to change the underlying owner channel.

Definition at line 1735 of file chan_motif.c.

References ao2_lock, ao2_unlock, ast_channel_tech_pvt(), jingle_set_owner(), and session.

1736 {
1737  struct jingle_session *session = ast_channel_tech_pvt(newchan);
1738 
1739  ao2_lock(session);
1740 
1741  jingle_set_owner(session, newchan);
1742 
1743  ao2_unlock(session);
1744 
1745  return 0;
1746 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ao2_unlock(a)
Definition: astobj2.h:730
Session which contains information about an active session.
Definition: chan_motif.c:296
static void jingle_set_owner(struct jingle_session *session, struct ast_channel *chan)
Set the channel owner on the jingle_session object and related objects.
Definition: chan_motif.c:656
static struct ast_mansession session
#define ao2_lock(a)
Definition: astobj2.h:718

◆ jingle_get_codec()

static void jingle_get_codec ( struct ast_channel chan,
struct ast_format_cap result 
)
static

Function called by RTP engine to get peer capabilities.

Definition at line 637 of file chan_motif.c.

638 {
639 }

◆ jingle_get_rtp_peer()

static enum ast_rtp_glue_result jingle_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance **  instance 
)
static

Function called by RTP engine to get local RTP peer.

Definition at line 621 of file chan_motif.c.

References ao2_ref, ast_channel_tech_pvt(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, jingle_session::rtp, and session.

622 {
625 
626  if (!session->rtp) {
628  }
629 
630  ao2_ref(session->rtp, +1);
631  *instance = session->rtp;
632 
633  return res;
634 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
Session which contains information about an active session.
Definition: chan_motif.c:296
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
ast_rtp_glue_result
Definition: rtp_engine.h:157

◆ jingle_hangup()

static int jingle_hangup ( struct ast_channel ast)
static

Function called by core to hang up a Jingle session.

Definition at line 1869 of file chan_motif.c.

References ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ARRAY_LEN, AST_CAUSE_CONGESTION, ast_channel_hangupcause(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), AST_STATE_DOWN, jingle_session::gone, jingle_reason_mappings, jingle_send_session_terminate(), jingle_set_owner(), NULL, jingle_session::owner, jingle_reason_mapping::reason, session, jingle_endpoint_state::sessions, and jingle_session::state.

1870 {
1872 
1873  ao2_lock(session);
1874 
1875  if ((ast_channel_state(ast) != AST_STATE_DOWN) && !session->gone) {
1876  int cause = (session->owner ? ast_channel_hangupcause(session->owner) : AST_CAUSE_CONGESTION);
1877  const char *reason = "success";
1878  int i;
1879 
1880  /* Get the appropriate reason and send a session-terminate */
1881  for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
1882  if (jingle_reason_mappings[i].cause == cause) {
1883  reason = jingle_reason_mappings[i].reason;
1884  break;
1885  }
1886  }
1887 
1888  jingle_send_session_terminate(session, reason);
1889  }
1890 
1892  jingle_set_owner(session, NULL);
1893 
1894  ao2_unlink(session->state->sessions, session);
1895  ao2_ref(session->state, -1);
1896 
1897  ao2_unlock(session);
1898  ao2_ref(session, -1);
1899 
1900  return 0;
1901 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct jingle_endpoint_state * state
Definition: chan_motif.c:302
void * ast_channel_tech_pvt(const struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct ast_channel * owner
Definition: chan_motif.c:310
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
Session which contains information about an active session.
Definition: chan_motif.c:296
static void jingle_send_session_terminate(struct jingle_session *session, const char *reasontext)
Internal function which sends a session-terminate message.
Definition: chan_motif.c:1058
static void jingle_set_owner(struct jingle_session *session, struct ast_channel *chan)
Set the channel owner on the jingle_session object and related objects.
Definition: chan_motif.c:656
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
static const struct jingle_reason_mapping jingle_reason_mappings[]
unsigned int gone
Definition: chan_motif.c:317
int ast_channel_hangupcause(const struct ast_channel *chan)
const char * reason
Definition: chan_motif.c:393
struct ao2_container * sessions
Definition: chan_motif.c:271
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
#define AST_CAUSE_CONGESTION
Definition: causes.h:152

◆ jingle_indicate()

static int jingle_indicate ( struct ast_channel ast,
int  condition,
const void *  data,
size_t  datalen 
)
static

Function called by core to ask the channel to indicate some sort of condition.

Definition at line 1749 of file chan_motif.c.

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, ast_channel_hangupcause_set(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_MASQUERADE_NOTIFY, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_CONTROL_VIDUPDATE, ast_log, ast_moh_start(), ast_moh_stop(), ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_UP, jingle_send_session_info(), LOG_NOTICE, NULL, jingle_session::rtp, and session.

1750 {
1752  int res = 0;
1753 
1754  switch (condition) {
1755  case AST_CONTROL_RINGING:
1756  if (ast_channel_state(ast) == AST_STATE_RING) {
1757  jingle_send_session_info(session, "ringing xmlns='urn:xmpp:jingle:apps:rtp:info:1'");
1758  } else {
1759  res = -1;
1760  }
1761  break;
1762  case AST_CONTROL_BUSY:
1763  if (ast_channel_state(ast) != AST_STATE_UP) {
1766  } else {
1767  res = -1;
1768  }
1769  break;
1771  if (ast_channel_state(ast) != AST_STATE_UP) {
1774  } else {
1775  res = -1;
1776  }
1777  break;
1779  if (ast_channel_state(ast) != AST_STATE_UP) {
1782  }
1783  break;
1784  case AST_CONTROL_HOLD:
1785  ast_moh_start(ast, data, NULL);
1786  break;
1787  case AST_CONTROL_UNHOLD:
1788  ast_moh_stop(ast);
1789  break;
1790  case AST_CONTROL_SRCUPDATE:
1791  if (session->rtp) {
1793  }
1794  break;
1795  case AST_CONTROL_SRCCHANGE:
1796  if (session->rtp) {
1798  }
1799  break;
1800  case AST_CONTROL_VIDUPDATE:
1803  break;
1806  case -1:
1807  res = -1;
1808  break;
1809  default:
1810  ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
1811  res = -1;
1812  }
1813 
1814  return res;
1815 }
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
Definition: rtp_engine.c:2160
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define NULL
Definition: resample.c:96
Session which contains information about an active session.
Definition: chan_motif.c:296
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7715
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
#define ast_log
Definition: astobj2.c:42
static struct ast_mansession session
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7705
#define LOG_NOTICE
Definition: logger.h:263
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2438
#define AST_CAUSE_BUSY
Definition: causes.h:148
static void jingle_send_session_info(struct jingle_session *session, const char *info)
Internal function which sends a session-info message.
Definition: chan_motif.c:1098
void ast_rtp_instance_update_source(struct ast_rtp_instance *instance)
Indicate that the RTP marker bit should be set on an RTP stream.
Definition: rtp_engine.c:2151
#define AST_CAUSE_CONGESTION
Definition: causes.h:152

◆ jingle_interpret_content()

static int jingle_interpret_content ( struct jingle_session session,
ikspak *  pak 
)
static

Helper function which locates content stanzas and interprets them.

Note
The session must not be locked before calling this

Definition at line 2279 of file chan_motif.c.

References ao2_ref, ao2_unlock, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_FACILITY_NOT_IMPLEMENTED, AST_CAUSE_SWITCH_CONGESTION, ast_channel_nativeformats_set(), ast_channel_unlock, ast_channel_unref, ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_format(), ast_log, AST_MEDIA_TYPE_UNKNOWN, ast_set_read_format(), ast_set_write_format(), ast_strlen_zero, jingle_session::audio_name, GOOGLE_PHONE_NS, GOOGLE_SESSION_NS, GOOGLE_TRANSPORT_NS, GOOGLE_VIDEO_NS, JINGLE_ICE_UDP_NS, jingle_interpret_description(), jingle_interpret_google_transport(), jingle_interpret_ice_udp_transport(), jingle_queue_hangup_with_cause(), JINGLE_RTP_NS, jingle_session_lock_full(), JINGLE_TRANSPORT_GOOGLE_V1, jingle_session::jointcap, LOG_ERROR, name, NULL, jingle_session::rtp, jingle_session::sid, jingle_session::transport, jingle_session::video_name, and jingle_session::vrtp.

Referenced by jingle_action_session_accept(), jingle_action_session_initiate(), and jingle_action_transport_info().

2280 {
2281  iks *content;
2282  unsigned int changed = 0;
2283  struct ast_channel *chan;
2284 
2285  /* Look at the content in the session initiation */
2286  for (content = iks_child(iks_child(pak->x)); content; content = iks_next(content)) {
2287  char *name;
2288  struct ast_rtp_instance *rtp = NULL;
2289  iks *description, *transport;
2290 
2291  /* Ignore specific parts if they are known not to be useful */
2292  if (!strcmp(iks_name(content), "conference-info")) {
2293  continue;
2294  }
2295 
2296  name = iks_find_attrib(content, "name");
2297 
2298  if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
2299  /* If this content stanza has no name consider it invalid and move on */
2300  if (ast_strlen_zero(name) && !(name = iks_find_attrib(content, "jin:name"))) {
2302  ast_log(LOG_ERROR, "Received content without a name on session '%s'\n", session->sid);
2303  return -1;
2304  }
2305 
2306  /* Try to pre-populate which RTP instance this content is relevant to */
2307  if (!strcmp(session->audio_name, name)) {
2308  rtp = session->rtp;
2309  } else if (!strcmp(session->video_name, name)) {
2310  rtp = session->vrtp;
2311  }
2312  } else {
2313  /* Google-V1 has no concept of assocating things like the above does, so since we only support audio over it assume they want audio */
2314  rtp = session->rtp;
2315  }
2316 
2317  /* If description information is available use it */
2318  if ((description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_RTP_NS)) ||
2319  (description = iks_find_with_attrib(content, "rtp:description", "xmlns:rtp", JINGLE_RTP_NS)) ||
2320  (description = iks_find_with_attrib(content, "pho:description", "xmlns:pho", GOOGLE_PHONE_NS)) ||
2321  (description = iks_find_with_attrib(pak->query, "description", "xmlns", GOOGLE_PHONE_NS)) ||
2322  (description = iks_find_with_attrib(pak->query, "pho:description", "xmlns:pho", GOOGLE_PHONE_NS)) ||
2323  (description = iks_find_with_attrib(pak->query, "vid:description", "xmlns", GOOGLE_VIDEO_NS))) {
2324  /* If we failed to do something with the content description abort immediately */
2325  if (jingle_interpret_description(session, description, name, &rtp)) {
2326  return -1;
2327  }
2328 
2329  /* If we successfully interpret the description then the codecs need updating */
2330  changed = 1;
2331  }
2332 
2333  /* If we get past the description handling and we still don't know what RTP instance this is for... it is unknown content */
2334  if (!rtp) {
2335  ast_log(LOG_ERROR, "Received a content stanza but have no RTP instance for it on session '%s'\n", session->sid);
2337  return -1;
2338  }
2339 
2340  /* If ICE UDP transport information is available use it */
2341  if ((transport = iks_find_with_attrib(content, "transport", "xmlns", JINGLE_ICE_UDP_NS))) {
2342  if (jingle_interpret_ice_udp_transport(session, transport, rtp)) {
2343  return -1;
2344  }
2345  } else if ((transport = iks_find_with_attrib(content, "transport", "xmlns", GOOGLE_TRANSPORT_NS)) ||
2346  (transport = iks_find_with_attrib(content, "p:transport", "xmlns:p", GOOGLE_TRANSPORT_NS)) ||
2347  (transport = iks_find_with_attrib(pak->x, "session", "xmlns", GOOGLE_SESSION_NS)) ||
2348  (transport = iks_find_with_attrib(pak->x, "ses:session", "xmlns:ses", GOOGLE_SESSION_NS))) {
2349  /* If Google transport support is available use it */
2350  if (jingle_interpret_google_transport(session, transport, rtp)) {
2351  return -1;
2352  }
2353  } else if (iks_find(content, "transport")) {
2354  /* If this is a transport we do not support terminate the session as it probably won't work out in the end */
2356  ast_log(LOG_ERROR, "Unsupported transport type received on session '%s'\n", session->sid);
2357  return -1;
2358  }
2359  }
2360 
2361  if (!changed) {
2362  return 0;
2363  }
2364 
2365  if ((chan = jingle_session_lock_full(session))) {
2366  struct ast_format_cap *caps;
2367  struct ast_format *fmt;
2368 
2370  if (caps) {
2372  ast_channel_nativeformats_set(chan, caps);
2373  ao2_ref(caps, -1);
2374  }
2375 
2376  fmt = ast_format_cap_get_format(session->jointcap, 0);
2377  ast_set_read_format(chan, fmt);
2378  ast_set_write_format(chan, fmt);
2379  ao2_ref(fmt, -1);
2380 
2381  ast_channel_unlock(chan);
2382  ast_channel_unref(chan);
2383  }
2384  ao2_unlock(session);
2385 
2386  return 0;
2387 }
const ast_string_field audio_name
Definition: chan_motif.c:301
const ast_string_field sid
Definition: chan_motif.c:301
Main Channel structure associated with a channel.
static int jingle_interpret_google_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
Helper function which handles Google transport information.
Definition: chan_motif.c:2201
#define GOOGLE_TRANSPORT_NS
Namespace for Google Talk ICE-UDP.
Definition: chan_motif.c:244
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
#define GOOGLE_PHONE_NS
Namespace for Google Phone description.
Definition: chan_motif.c:253
static int jingle_interpret_ice_udp_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
Helper function which handles ICE-UDP transport information.
Definition: chan_motif.c:2120
Definition of a media format.
Definition: format.c:43
struct ast_format_cap * jointcap
Definition: chan_motif.c:314
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
static int jingle_interpret_description(struct jingle_session *session, iks *description, const char *name, struct ast_rtp_instance **rtp)
Helper function which handles content descriptions.
Definition: chan_motif.c:2033
#define ast_log
Definition: astobj2.c:42
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5724
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5765
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
#define AST_CAUSE_FACILITY_NOT_IMPLEMENTED
Definition: causes.h:132
#define LOG_ERROR
Definition: logger.h:285
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
Definition: chan_motif.c:1197
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_rtp_instance * vrtp
Definition: chan_motif.c:312
#define JINGLE_RTP_NS
Namespace for Jingle RTP sessions.
Definition: chan_motif.c:235
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
static const char name[]
Definition: cdr_mysql.c:74
#define GOOGLE_VIDEO_NS
Namespace for Google Video description.
Definition: chan_motif.c:256
enum jingle_transport transport
Definition: chan_motif.c:304
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148
#define JINGLE_ICE_UDP_NS
Namespace for Jingle ICE-UDP.
Definition: chan_motif.c:241
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
#define GOOGLE_SESSION_NS
Namespace for Google Session.
Definition: chan_motif.c:250
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
const ast_string_field video_name
Definition: chan_motif.c:301
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:129

◆ jingle_interpret_description()

static int jingle_interpret_description ( struct jingle_session session,
iks *  description,
const char *  name,
struct ast_rtp_instance **  rtp 
)
static

Helper function which handles content descriptions.

Definition at line 2033 of file chan_motif.c.

References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, ast_format_cap_count(), ast_format_cap_get_compatible(), ast_format_cap_remove_by_type(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_rtp_codecs_payload_formats(), ast_rtp_codecs_payloads_copy(), ast_rtp_codecs_payloads_destroy(), ast_rtp_codecs_payloads_initialize(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_codecs_payloads_set_rtpmap_type_rate(), ast_rtp_instance_get_codecs(), ast_string_field_set, ast_strlen_zero, jingle_session::cap, jingle_enable_video(), jingle_queue_hangup_with_cause(), JINGLE_TRANSPORT_GOOGLE_V1, jingle_session::jointcap, LOG_ERROR, NULL, jingle_session::peercap, jingle_session::rtp, jingle_session::sid, jingle_session::transport, and jingle_session::vrtp.

Referenced by jingle_interpret_content().

2034 {
2035  char *media = iks_find_attrib(description, "media");
2036  struct ast_rtp_codecs codecs;
2037  iks *codec;
2038  int othercapability = 0;
2039 
2040  /* Google-V1 is always carrying audio, but just doesn't tell us so */
2041  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
2042  media = "audio";
2043  } else if (ast_strlen_zero(media)) {
2045  ast_log(LOG_ERROR, "Received a content description on session '%s' without a name\n", session->sid);
2046  return -1;
2047  }
2048 
2049  /* Determine the type of media that is being carried and update the RTP instance, as well as the name */
2050  if (!strcasecmp(media, "audio")) {
2051  if (!ast_strlen_zero(name)) {
2052  ast_string_field_set(session, audio_name, name);
2053  }
2054  *rtp = session->rtp;
2057  } else if (!strcasecmp(media, "video")) {
2058  if (!ast_strlen_zero(name)) {
2059  ast_string_field_set(session, video_name, name);
2060  }
2061 
2062  jingle_enable_video(session);
2063  *rtp = session->vrtp;
2064 
2065  /* If video is not present cancel this session */
2066  if (!session->vrtp) {
2068  ast_log(LOG_ERROR, "Received a video content description on session '%s' but could not enable video\n", session->sid);
2069  return -1;
2070  }
2071 
2074  } else {
2075  /* Unknown media type */
2077  ast_log(LOG_ERROR, "Unsupported media type '%s' received in content description on session '%s'\n", media, session->sid);
2078  return -1;
2079  }
2080 
2083  ast_log(LOG_ERROR, "Could not initialize codecs for negotiation on session '%s'\n", session->sid);
2084  return -1;
2085  }
2086 
2087  /* Iterate the codecs updating the relevant RTP instance as we go */
2088  for (codec = iks_child(description); codec; codec = iks_next(codec)) {
2089  char *id = iks_find_attrib(codec, "id");
2090  char *attr_name = iks_find_attrib(codec, "name");
2091  char *clockrate = iks_find_attrib(codec, "clockrate");
2092  int rtp_id, rtp_clockrate;
2093 
2094  if (!ast_strlen_zero(id) && !ast_strlen_zero(attr_name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
2095  if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
2096  ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, attr_name, 0, rtp_clockrate);
2097  } else {
2098  ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, rtp_id, media, attr_name, 0);
2099  }
2100  }
2101  }
2102 
2103  ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability);
2104  ast_format_cap_get_compatible(session->cap, session->peercap, session->jointcap);
2105 
2106  if (!ast_format_cap_count(session->jointcap)) {
2107  /* We have no compatible codecs, so terminate the session appropriately */
2110  return -1;
2111  }
2112 
2115 
2116  return 0;
2117 }
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
Retrieve all formats that were found.
Definition: rtp_engine.c:1580
const ast_string_field sid
Definition: chan_motif.c:301
static void jingle_enable_video(struct jingle_session *session)
Internal helper function which enables video support on a sesson if possible.
Definition: chan_motif.c:668
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
struct ast_format_cap * jointcap
Definition: chan_motif.c:314
#define NULL
Definition: resample.c:96
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
#define ast_log
Definition: astobj2.c:42
struct ast_format_cap * cap
Definition: chan_motif.c:313
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
Record tx payload type information that was seen in an a=rtpmap: SDP line.
Definition: rtp_engine.c:1428
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:525
#define LOG_ERROR
Definition: logger.h:285
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
Definition: chan_motif.c:1197
struct ast_rtp_instance * vrtp
Definition: chan_motif.c:312
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
Destroy the contents of an RTP codecs structure (but not the structure itself)
Definition: rtp_engine.c:974
void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Copy payload information from one RTP instance to another.
Definition: rtp_engine.c:1224
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:958
enum jingle_transport transport
Definition: chan_motif.c:304
int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt, char *mimetype, char *mimesubtype, enum ast_rtp_options options, unsigned int sample_rate)
Set tx payload type to a known MIME media type for a codec with a specific sample rate...
Definition: rtp_engine.c:1343
struct ast_format_cap * peercap
Definition: chan_motif.c:315
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:129
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:630
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ jingle_interpret_google_transport()

static int jingle_interpret_google_transport ( struct jingle_session session,
iks *  transport,
struct ast_rtp_instance rtp 
)
static

Helper function which handles Google transport information.

Definition at line 2201 of file chan_motif.c.

References AST_CAUSE_PROTOCOL_ERROR, AST_CAUSE_SWITCH_CONGESTION, ast_log, ast_rtp_instance_get_ice(), ast_rtp_instance_stun_request(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_strlen_zero, ast_rtp_engine_ice::get_ufrag, jingle_queue_hangup_with_cause(), JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, LOG_ERROR, name, PARSE_PORT_FORBID, jingle_session::sid, ast_rtp_engine_ice::stop, and jingle_session::transport.

Referenced by jingle_interpret_content().

2202 {
2203  struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(rtp);
2204  iks *candidate;
2205 
2206  if (!ice) {
2208  ast_log(LOG_ERROR, "Received Google transport information on session '%s' but ICE support not available\n", session->sid);
2209  return -1;
2210  }
2211 
2212  /* If this session has not transitioned to the Google transport do so now */
2213  if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V2) &&
2214  (session->transport != JINGLE_TRANSPORT_GOOGLE_V1)) {
2215  /* Stop built-in ICE support... we need to fall back to the old old old STUN */
2216  ice->stop(rtp);
2217 
2219  }
2220 
2221  for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
2222  char *address = iks_find_attrib(candidate, "address"), *port = iks_find_attrib(candidate, "port");
2223  char *username = iks_find_attrib(candidate, "username"), *name = iks_find_attrib(candidate, "name");
2224  char *protocol = iks_find_attrib(candidate, "protocol");
2225  int real_port;
2226  struct ast_sockaddr target = { { 0, } };
2227  /* In Google land the combined value is 32 bytes */
2228  char combined[33] = "";
2229 
2230  /* If this is NOT actually a candidate just skip it */
2231  if (strcasecmp(iks_name(candidate), "candidate") &&
2232  strcasecmp(iks_name(candidate), "p:candidate") &&
2233  strcasecmp(iks_name(candidate), "ses:candidate")) {
2234  continue;
2235  }
2236 
2237  /* If this candidate is incomplete skip it */
2238  if (ast_strlen_zero(address) || ast_strlen_zero(port) || ast_strlen_zero(username) ||
2239  ast_strlen_zero(name)) {
2241  ast_log(LOG_ERROR, "Incomplete Google candidate received on session '%s'\n", session->sid);
2242  return -1;
2243  }
2244 
2245  /* We only support UDP so skip any other protocols */
2246  if (!ast_strlen_zero(protocol) && strcasecmp(protocol, "udp")) {
2247  continue;
2248  }
2249 
2250  /* We only permit audio and video, not RTCP */
2251  if (strcasecmp(name, "rtp") && strcasecmp(name, "video_rtp")) {
2252  continue;
2253  }
2254 
2255  /* Parse the target information so we can send a STUN request to the candidate */
2256  if (sscanf(port, "%30d", &real_port) != 1) {
2258  ast_log(LOG_ERROR, "Invalid Google candidate port '%s' received on session '%s'\n", port, session->sid);
2259  return -1;
2260  }
2261  ast_sockaddr_parse(&target, address, PARSE_PORT_FORBID);
2262  ast_sockaddr_set_port(&target, real_port);
2263 
2264  /* Per the STUN support Google talk uses combine the two usernames */
2265  snprintf(combined, sizeof(combined), "%s%s", username, ice->get_ufrag(rtp));
2266 
2267  /* This should appease the masses... we will actually change the remote address when we get their STUN packet */
2268  ast_rtp_instance_stun_request(rtp, &target, combined);
2269  }
2270 
2271  return 0;
2272 }
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:144
const ast_string_field sid
Definition: chan_motif.c:301
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
char * address
Definition: f2c.h:59
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:492
Socket address structure.
Definition: netsock2.h:97
void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
Request that the underlying RTP engine send a STUN BIND request.
Definition: rtp_engine.c:2661
#define ast_log
Definition: astobj2.c:42
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:494
#define LOG_ERROR
Definition: logger.h:285
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
Definition: chan_motif.c:1197
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
enum jingle_transport transport
Definition: chan_motif.c:304
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484

◆ jingle_interpret_ice_udp_transport()

static int jingle_interpret_ice_udp_transport ( struct jingle_session session,
iks *  transport,
struct ast_rtp_instance rtp 
)
static

Helper function which handles ICE-UDP transport information.

Definition at line 2120 of file chan_motif.c.

References ast_rtp_engine_ice::add_remote_candidate, ast_rtp_engine_ice_candidate::address, AST_CAUSE_PROTOCOL_ERROR, AST_CAUSE_SWITCH_CONGESTION, ast_log, AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, ast_rtp_instance_get_ice(), ast_rtp_instance_get_remote_address, ast_rtp_instance_set_remote_address, ast_sockaddr_is_ipv4(), ast_sockaddr_isnull(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_strlen_zero, ast_rtp_engine_ice_candidate::foundation, ast_rtp_engine_ice_candidate::id, jingle_queue_hangup_with_cause(), LOG_ERROR, PARSE_PORT_FORBID, priority, ast_rtp_engine_ice_candidate::priority, ast_rtp_engine_ice::set_authentication, jingle_session::sid, ast_rtp_engine_ice::start, ast_rtp_engine_ice_candidate::transport, type, and ast_rtp_engine_ice_candidate::type.

Referenced by jingle_interpret_content().

2121 {
2122  struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(rtp);
2123  char *ufrag = iks_find_attrib(transport, "ufrag"), *pwd = iks_find_attrib(transport, "pwd");
2124  iks *candidate;
2125 
2126  if (!ice) {
2128  ast_log(LOG_ERROR, "Received ICE-UDP transport information on session '%s' but ICE support not available\n", session->sid);
2129  return -1;
2130  }
2131 
2132  if (!ast_strlen_zero(ufrag) && !ast_strlen_zero(pwd)) {
2133  ice->set_authentication(rtp, ufrag, pwd);
2134  }
2135 
2136  for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
2137  char *component = iks_find_attrib(candidate, "component"), *foundation = iks_find_attrib(candidate, "foundation");
2138  char *generation = iks_find_attrib(candidate, "generation"), *id = iks_find_attrib(candidate, "id");
2139  char *ip = iks_find_attrib(candidate, "ip"), *port = iks_find_attrib(candidate, "port");
2140  char *priority = iks_find_attrib(candidate, "priority"), *protocol = iks_find_attrib(candidate, "protocol");
2141  char *type = iks_find_attrib(candidate, "type");
2142  struct ast_rtp_engine_ice_candidate local_candidate = { 0, };
2143  int real_port;
2144  struct ast_sockaddr remote_address = { { 0, } };
2145 
2146  /* If this candidate is incomplete skip it */
2147  if (ast_strlen_zero(component) || ast_strlen_zero(foundation) || ast_strlen_zero(generation) || ast_strlen_zero(id) ||
2148  ast_strlen_zero(ip) || ast_strlen_zero(port) || ast_strlen_zero(priority) ||
2149  ast_strlen_zero(protocol) || ast_strlen_zero(type)) {
2151  ast_log(LOG_ERROR, "Incomplete ICE-UDP candidate received on session '%s'\n", session->sid);
2152  return -1;
2153  }
2154 
2155  if ((sscanf(component, "%30u", &local_candidate.id) != 1) ||
2156  (sscanf(priority, "%30u", (unsigned *)&local_candidate.priority) != 1) ||
2157  (sscanf(port, "%30d", &real_port) != 1)) {
2159  ast_log(LOG_ERROR, "Invalid ICE-UDP candidate information received on session '%s'\n", session->sid);
2160  return -1;
2161  }
2162 
2163  local_candidate.foundation = foundation;
2164  local_candidate.transport = protocol;
2165 
2166  ast_sockaddr_parse(&local_candidate.address, ip, PARSE_PORT_FORBID);
2167 
2168  /* We only support IPv4 right now */
2169  if (!ast_sockaddr_is_ipv4(&local_candidate.address)) {
2170  continue;
2171  }
2172 
2173  ast_sockaddr_set_port(&local_candidate.address, real_port);
2174 
2175  if (!strcasecmp(type, "host")) {
2176  local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_HOST;
2177  } else if (!strcasecmp(type, "srflx")) {
2178  local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_SRFLX;
2179  } else if (!strcasecmp(type, "relay")) {
2180  local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED;
2181  } else {
2182  continue;
2183  }
2184 
2185  /* Worst case use the first viable address */
2186  ast_rtp_instance_get_remote_address(rtp, &remote_address);
2187 
2188  if (ast_sockaddr_is_ipv4(&local_candidate.address) && ast_sockaddr_isnull(&remote_address)) {
2189  ast_rtp_instance_set_remote_address(rtp, &local_candidate.address);
2190  }
2191 
2192  ice->add_remote_candidate(rtp, &local_candidate);
2193  }
2194 
2195  ice->start(rtp);
2196 
2197  return 0;
2198 }
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:144
static const char type[]
Definition: chan_ooh323.c:109
const ast_string_field sid
Definition: chan_motif.c:301
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:488
static int priority
Structure for an ICE candidate.
Definition: rtp_engine.h:473
Socket address structure.
Definition: netsock2.h:97
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:480
#define ast_log
Definition: astobj2.c:42
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:486
#define LOG_ERROR
Definition: logger.h:285
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
Definition: chan_motif.c:1197
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1079
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:475
#define ast_strlen_zero(a)
Definition: muted.c:73
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:490
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
struct ast_sockaddr address
Definition: rtp_engine.h:478
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1191

◆ jingle_new()

static struct ast_channel* jingle_new ( struct jingle_endpoint endpoint,
struct jingle_session session,
int  state,
const char *  title,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  cid_name 
)
static

Function called to create a new Jingle Asterisk channel.

Definition at line 768 of file chan_motif.c.

References jingle_endpoint::accountcode, ao2_lock, ao2_ref, ao2_unlock, AST_ADSI_UNAVAILABLE, ast_channel_adsicpe_set(), ast_channel_alloc_with_endpoint, ast_channel_callgroup_set(), ast_channel_callid_set(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_nativeformats_set(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_unlock, ast_exists_extension(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_format(), ast_format_cap_get_framing(), AST_MEDIA_TYPE_UNKNOWN, ast_random(), ast_rtp_codecs_set_framing(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_ice(), AST_STATE_RING, ast_strlen_zero, jingle_endpoint::callgroup, jingle_session::callid, jingle_session::cap, jingle_endpoint::connection, jingle_endpoint::context, ast_xmpp_client::endpoint, jingle_set_owner(), JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, jingle_endpoint::language, jingle_endpoint::musicclass, jingle_endpoint::name, NULL, jingle_endpoint::pickupgroup, jingle_session::remote, jingle_session::rtp, S_OR, ast_rtp_engine_ice::stop, str, and jingle_session::transport.

Referenced by jingle_action_session_initiate(), and jingle_request().

769 {
770  struct ast_channel *chan;
771  const char *str = S_OR(title, session->remote);
772  struct ast_format_cap *caps;
773  struct ast_format *tmpfmt;
774 
775  if (!ast_format_cap_count(session->cap)) {
776  return NULL;
777  }
778 
780  if (!caps) {
781  return NULL;
782  }
783 
784  if (!(chan = ast_channel_alloc_with_endpoint(1, state, S_OR(title, ""), S_OR(cid_name, ""), "", "", "", assignedids, requestor, 0, endpoint->connection->endpoint, "Motif/%s-%04lx", str, (unsigned long)(ast_random() & 0xffff)))) {
785  ao2_ref(caps, -1);
786  return NULL;
787  }
788 
790 
792  ast_channel_tech_pvt_set(chan, session);
793  jingle_set_owner(session, chan);
794 
795  ast_channel_callid_set(chan, session->callid);
796 
798  ast_channel_nativeformats_set(chan, caps);
799  ao2_ref(caps, -1);
800 
801  if (session->rtp) {
802  struct ast_rtp_engine_ice *ice;
803 
804  ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(session->rtp, 0));
805  ast_channel_set_fd(chan, 1, ast_rtp_instance_fd(session->rtp, 1));
807  ast_format_cap_get_framing(session->cap));
808 
809  if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
810  (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
811  (ice = ast_rtp_instance_get_ice(session->rtp))) {
812  /* We stop built in ICE support because we need to fall back to old old old STUN support */
813  ice->stop(session->rtp);
814  }
815  }
816 
817  if (state == AST_STATE_RING) {
818  ast_channel_rings_set(chan, 1);
819  }
820 
822 
823  tmpfmt = ast_format_cap_get_format(session->cap, 0);
824  ast_channel_set_writeformat(chan, tmpfmt);
825  ast_channel_set_rawwriteformat(chan, tmpfmt);
826  ast_channel_set_readformat(chan, tmpfmt);
827  ast_channel_set_rawreadformat(chan, tmpfmt);
828  ao2_ref(tmpfmt, -1);
829 
830  ao2_lock(endpoint);
831 
832  ast_channel_callgroup_set(chan, endpoint->callgroup);
833  ast_channel_pickupgroup_set(chan, endpoint->pickupgroup);
834 
835  if (!ast_strlen_zero(endpoint->accountcode)) {
836  ast_channel_accountcode_set(chan, endpoint->accountcode);
837  }
838 
839  if (!ast_strlen_zero(endpoint->language)) {
840  ast_channel_language_set(chan, endpoint->language);
841  }
842 
843  if (!ast_strlen_zero(endpoint->musicclass)) {
844  ast_channel_musicclass_set(chan, endpoint->musicclass);
845  }
846 
847  ast_channel_context_set(chan, endpoint->context);
848  if (ast_exists_extension(NULL, endpoint->context, endpoint->name, 1, NULL)) {
849  ast_channel_exten_set(chan, endpoint->name);
850  } else {
851  ast_channel_exten_set(chan, "s");
852  }
853  ast_channel_priority_set(chan, 1);
854 
855  ao2_unlock(endpoint);
856 
858  ast_channel_unlock(chan);
859 
860  return chan;
861 }
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
Main Channel structure associated with a channel.
static struct ast_channel_tech jingle_tech
PBX interface structure for channel registration.
Definition: chan_motif.c:353
unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
Get the global framing.
Definition: format_cap.c:438
#define ast_channel_alloc_with_endpoint(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, endpoint,...)
Definition: channel.h:1246
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
ast_callid callid
Definition: chan_motif.c:318
const ast_string_field language
Definition: chan_motif.c:283
const ast_string_field name
Definition: chan_motif.c:283
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
Definition of a media format.
Definition: format.c:43
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
#define ao2_unlock(a)
Definition: astobj2.h:730
ast_group_t pickupgroup
Definition: chan_motif.c:290
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
Definition: rtp_engine.c:1558
const char * str
Definition: app_jack.c:147
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:492
#define NULL
Definition: resample.c:96
ast_group_t callgroup
Definition: chan_motif.c:289
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
const ast_string_field context
Definition: chan_motif.c:283
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
const ast_string_field musicclass
Definition: chan_motif.c:283
static void jingle_set_owner(struct jingle_session *session, struct ast_channel *chan)
Set the channel owner on the jingle_session object and related objects.
Definition: chan_motif.c:656
struct ast_format_cap * cap
Definition: chan_motif.c:313
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
long int ast_random(void)
Definition: main/utils.c:1935
#define ao2_lock(a)
Definition: astobj2.h:718
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4170
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
struct ast_endpoint * endpoint
Definition: xmpp.h:148
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:2192
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
char remote[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:308
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2406
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:165
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
enum jingle_transport transport
Definition: chan_motif.c:304
const ast_string_field accountcode
Definition: chan_motif.c:283
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
void ast_channel_priority_set(struct ast_channel *chan, int value)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)

◆ jingle_outgoing_hook()

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

Callback for when a response is received for an outgoing session-initiate message.

Definition at line 1524 of file chan_motif.c.

References ao2_unlock, ast_callid_threadassoc_add(), ast_callid_threadassoc_remove(), AST_CAUSE_CONGESTION, AST_CAUSE_FACILITY_NOT_IMPLEMENTED, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_PROTOCOL_ERROR, AST_CAUSE_REQUESTED_CHAN_UNAVAIL, ast_channel_unlock, ast_channel_unref, AST_CONTROL_PROCEEDING, ast_copy_string(), ast_queue_control(), ast_rtp_instance_get_ice(), ast_strlen_zero, jingle_session::callid, jingle_session::connection, end, error(), ast_xmpp_client::filter, jingle_session::gone, jingle_queue_hangup_with_cause(), jingle_send_session_initiate(), jingle_send_transport_info(), jingle_session_lock_full(), JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, JINGLE_TRANSPORT_NONE, ast_xmpp_client::mid, NULL, jingle_session::remote, jingle_session::remote_original, jingle_session::rtp, jingle_session::rule, session, ast_rtp_engine_ice::stop, jingle_session::transport, and XMPP_STANZAS_NS.

Referenced by jingle_call().

1525 {
1526  struct jingle_session *session = data;
1527  iks *error = iks_find(pak->x, "error"), *redirect;
1528 
1529  /* In all cases this hook is done with */
1530  iks_filter_remove_rule(session->connection->filter, session->rule);
1531  session->rule = NULL;
1532 
1534 
1535  /* If no error occurred they accepted our session-initiate message happily */
1536  if (!error) {
1537  struct ast_channel *chan;
1538 
1539  if ((chan = jingle_session_lock_full(session))) {
1541  ast_channel_unlock(chan);
1542  ast_channel_unref(chan);
1543  }
1544  ao2_unlock(session);
1545 
1546  jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
1547 
1548  goto end;
1549  }
1550 
1551  /* Assume that because this is an error the session is gone, there is only one case where this is incorrect - a redirect */
1552  session->gone = 1;
1553 
1554  /* Map the error we received to an appropriate cause code and hang up the channel */
1555  if ((redirect = iks_find_with_attrib(error, "redirect", "xmlns", XMPP_STANZAS_NS))) {
1556  iks *to = iks_child(redirect);
1557  char *target;
1558 
1559  if (to && (target = iks_name(to)) && !ast_strlen_zero(target)) {
1560  /* Make the xmpp: go away if it is present */
1561  if (!strncmp(target, "xmpp:", 5)) {
1562  target += 5;
1563  }
1564 
1565  /* This is actually a fairly simple operation - we update the remote and send another session-initiate */
1566  ast_copy_string(session->remote, target, sizeof(session->remote));
1567 
1568  /* Add a new hook so we can get the status of redirected session */
1569  session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1570  IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1571 
1573 
1574  session->gone = 0;
1575  } else {
1577  }
1578  } else if (iks_find_with_attrib(error, "service-unavailable", "xmlns", XMPP_STANZAS_NS)) {
1580  } else if (iks_find_with_attrib(error, "resource-constraint", "xmlns", XMPP_STANZAS_NS)) {
1582  } else if (iks_find_with_attrib(error, "bad-request", "xmlns", XMPP_STANZAS_NS)) {
1584  } else if (iks_find_with_attrib(error, "remote-server-not-found", "xmlns", XMPP_STANZAS_NS)) {
1586  } else if (iks_find_with_attrib(error, "feature-not-implemented", "xmlns", XMPP_STANZAS_NS)) {
1587  /* Assume that this occurred because the remote side does not support our transport, so drop it down one and try again */
1588  session->transport--;
1589 
1590  /* If we still have a viable transport mechanism re-send the session-initiate */
1591  if (session->transport != JINGLE_TRANSPORT_NONE) {
1592  struct ast_rtp_engine_ice *ice;
1593 
1594  if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
1595  (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
1596  (ice = ast_rtp_instance_get_ice(session->rtp))) {
1597  /* We stop built in ICE support because we need to fall back to old old old STUN support */
1598  ice->stop(session->rtp);
1599  }
1600 
1601  /* Re-send the message to the *original* target and not a redirected one */
1602  ast_copy_string(session->remote, session->remote_original, sizeof(session->remote));
1603 
1604  session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1605  IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1606 
1608 
1609  session->gone = 0;
1610  } else {
1611  /* Otherwise we have exhausted all transports */
1613  }
1614  } else {
1616  }
1617 
1618 end:
1620 
1621  return IKS_FILTER_EAT;
1622 }
#define AST_CAUSE_PROTOCOL_ERROR
Definition: causes.h:144
Main Channel structure associated with a channel.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1227
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
ast_callid callid
Definition: chan_motif.c:318
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
#define ao2_unlock(a)
Definition: astobj2.h:730
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:492
#define NULL
Definition: resample.c:96
Session which contains information about an active session.
Definition: chan_motif.c:296
char * end
Definition: eagi_proxy.c:73
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:1911
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:1892
static struct ast_mansession session
#define AST_CAUSE_FACILITY_NOT_IMPLEMENTED
Definition: causes.h:132
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
Definition: chan_motif.c:1197
char remote_original[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:307
iksfilter * filter
Definition: xmpp.h:128
static int jingle_outgoing_hook(void *data, ikspak *pak)
Callback for when a response is received for an outgoing session-initiate message.
Definition: chan_motif.c:1524
struct ast_xmpp_client * connection
Definition: chan_motif.c:303
#define XMPP_STANZAS_NS
Namespace for XMPP stanzas.
Definition: chan_motif.c:259
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
unsigned int gone
Definition: chan_motif.c:317
char remote[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:308
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:124
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:99
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
enum jingle_transport transport
Definition: chan_motif.c:304
char mid[6]
Definition: xmpp.h:125
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148
static void jingle_send_transport_info(struct jingle_session *session, const char *from)
Internal function which sends a transport-info message.
Definition: chan_motif.c:1211
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
static void jingle_send_session_initiate(struct jingle_session *session)
Internal function which sends a session-inititate message.
Definition: chan_motif.c:1512
int error(const char *format,...)
Definition: utils/frame.c:999
iksrule * rule
Definition: chan_motif.c:309
#define AST_CAUSE_CONGESTION
Definition: causes.h:152

◆ jingle_queue_hangup_with_cause()

static void jingle_queue_hangup_with_cause ( struct jingle_session session,
int  cause 
)
static

Helper function which queues a hangup frame with cause code.

Definition at line 1197 of file chan_motif.c.

References ao2_unlock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_queue_hangup_with_cause(), and jingle_session_lock_full().

Referenced by jingle_interpret_content(), jingle_interpret_description(), jingle_interpret_google_transport(), jingle_interpret_ice_udp_transport(), jingle_outgoing_hook(), jingle_send_session_action(), and jingle_send_transport_info().

1198 {
1199  struct ast_channel *chan;
1200 
1201  if ((chan = jingle_session_lock_full(session))) {
1202  ast_debug(3, "Hanging up channel '%s' with cause '%d'\n", ast_channel_name(chan), cause);
1203  ast_queue_hangup_with_cause(chan, cause);
1204  ast_channel_unlock(chan);
1205  ast_channel_unref(chan);
1206  }
1207  ao2_unlock(session);
1208 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
#define ao2_unlock(a)
Definition: astobj2.h:730
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1162
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_channel_unlock(chan)
Definition: channel.h:2838
const char * ast_channel_name(const struct ast_channel *chan)
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148

◆ jingle_read()

static struct ast_frame * jingle_read ( struct ast_channel ast)
static

Function called by core to read any waiting frames.

Definition at line 1640 of file chan_motif.c.

References ao2_ref, ast_channel_fdno(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_nativeformats_set(), ast_channel_readformat(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_debug, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_iscompatible_format(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_VOICE, ast_frfree, ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), ast_frame_subclass::format, ast_frame::frametype, jingle_session::jointcap, jingle_session::rtp, session, ast_frame::subclass, and jingle_session::vrtp.

1641 {
1643  struct ast_frame *frame = &ast_null_frame;
1644 
1645  switch (ast_channel_fdno(ast)) {
1646  case 0:
1647  if (session->rtp) {
1648  frame = ast_rtp_instance_read(session->rtp, 0);
1649  }
1650  break;
1651  case 1:
1652  if (session->rtp) {
1653  frame = ast_rtp_instance_read(session->rtp, 1);
1654  }
1655  break;
1656  case 2:
1657  if (session->vrtp) {
1658  frame = ast_rtp_instance_read(session->vrtp, 0);
1659  }
1660  break;
1661  case 3:
1662  if (session->vrtp) {
1663  frame = ast_rtp_instance_read(session->vrtp, 1);
1664  }
1665  break;
1666  default:
1667  break;
1668  }
1669 
1670  if (frame && frame->frametype == AST_FRAME_VOICE &&
1673  ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
1675  ast_frfree(frame);
1676  frame = &ast_null_frame;
1677  } else {
1678  struct ast_format_cap *caps;
1679 
1680  ast_debug(1, "Oooh, format changed to %s\n",
1682 
1684  if (caps) {
1685  ast_format_cap_append(caps, frame->subclass.format, 0);
1686  ast_channel_nativeformats_set(ast, caps);
1687  ao2_ref(caps, -1);
1688  }
1691  }
1692  }
1693 
1694  return frame;
1695 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_format_cap * jointcap
Definition: chan_motif.c:314
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Session which contains information about an active session.
Definition: chan_motif.c:296
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
struct ast_frame_subclass subclass
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:583
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5724
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5765
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
int ast_channel_fdno(const struct ast_channel *chan)
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_rtp_instance * vrtp
Definition: chan_motif.c:312
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_frame ast_null_frame
Definition: main/frame.c:79
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
Data structure associated with a single frame of data.
enum ast_frame_type frametype
struct ast_format * format
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:578

◆ jingle_request()

static struct ast_channel * jingle_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_assigned_ids assignedids,
const struct ast_channel requestor,
const char *  data,
int *  cause 
)
static

Function called by core to create a new outgoing Jingle session.

Definition at line 1904 of file chan_motif.c.

References ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, args, AST_APP_ARG, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_CHANNEL_UNACCEPTABLE, AST_CAUSE_SWITCH_CONGESTION, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_format_cap_has_type(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_NONSTANDARD_APP_ARGS, ast_rtp_instance_get_ice(), AST_STATE_DOWN, ast_strdupa, ast_strlen_zero, ast_xmpp_resource::caps, ast_channel::dialed, globals, ast_xmpp_capabilities::google, ast_rtp_engine_ice::ice_lite, ast_xmpp_capabilities::jingle, jingle_alloc(), jingle_enable_video(), jingle_endpoint_find(), jingle_new(), JINGLE_TRANSPORT_GOOGLE_V2, JINGLE_TRANSPORT_ICE_UDP, JINGLE_TRANSPORT_NONE, LOG_ERROR, name, NULL, OBJ_KEY, RAII_VAR, ast_xmpp_resource::resource, ast_xmpp_buddy::resources, jingle_session::rtp, session, jingle_session::transport, and jingle_session::vrtp.

1905 {
1907  RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
1908  char *dialed, target[1024] = "";
1909  struct ast_xmpp_buddy *buddy;
1910  struct jingle_session *session;
1911  struct ast_channel *chan;
1912  enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
1913  struct ast_rtp_engine_ice *ice;
1915  AST_APP_ARG(name);
1916  AST_APP_ARG(target);
1917  );
1918 
1919  /* We require at a minimum one audio format to be requested */
1921  ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n");
1923  return NULL;
1924  }
1925 
1926  if (ast_strlen_zero(data) || !(dialed = ast_strdupa(data))) {
1927  ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
1929  return NULL;
1930  }
1931 
1932  /* Parse the given dial string and validate the results */
1933  AST_NONSTANDARD_APP_ARGS(args, dialed, '/');
1934 
1935  if (ast_strlen_zero(args.name) || ast_strlen_zero(args.target)) {
1936  ast_log(LOG_ERROR, "Unable to determine endpoint name and target.\n");
1938  return NULL;
1939  }
1940 
1941  if (!(endpoint = jingle_endpoint_find(cfg->endpoints, args.name))) {
1942  ast_log(LOG_ERROR, "Endpoint '%s' does not exist.\n", args.name);
1944  return NULL;
1945  }
1946 
1947  ao2_lock(endpoint->state);
1948 
1949  /* If we don't have a connection for the endpoint we can't exactly start a session on it */
1950  if (!endpoint->connection) {
1951  ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no valid connection exists\n", args.name);
1952  *cause = AST_CAUSE_SWITCH_CONGESTION;
1953  ao2_unlock(endpoint->state);
1954  return NULL;
1955  }
1956 
1957  /* Find the target in the roster so we can choose a resource */
1958  if ((buddy = ao2_find(endpoint->connection->buddies, args.target, OBJ_KEY))) {
1959  struct ao2_iterator res;
1960  struct ast_xmpp_resource *resource;
1961 
1962  /* Iterate through finding the first viable Jingle capable resource */
1963  res = ao2_iterator_init(buddy->resources, 0);
1964  while ((resource = ao2_iterator_next(&res))) {
1965  if (resource->caps.jingle) {
1966  snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
1967  transport = JINGLE_TRANSPORT_ICE_UDP;
1968  break;
1969  } else if (resource->caps.google) {
1970  snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
1971  transport = JINGLE_TRANSPORT_GOOGLE_V2;
1972  break;
1973  }
1974  ao2_ref(resource, -1);
1975  }
1976  ao2_iterator_destroy(&res);
1977 
1978  ao2_ref(buddy, -1);
1979  } else {
1980  /* If the target is NOT in the roster use the provided target as-is */
1981  ast_copy_string(target, args.target, sizeof(target));
1982  }
1983 
1984  ao2_unlock(endpoint->state);
1985 
1986  /* If no target was found we can't set up a session */
1987  if (ast_strlen_zero(target)) {
1988  ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no capable resource for target '%s' was found\n", args.name, args.target);
1989  *cause = AST_CAUSE_SWITCH_CONGESTION;
1990  return NULL;
1991  }
1992 
1993  if (!(session = jingle_alloc(endpoint, target, NULL))) {
1994  ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s'\n", args.name);
1995  *cause = AST_CAUSE_SWITCH_CONGESTION;
1996  return NULL;
1997  }
1998 
1999  /* Update the transport if we learned what we should actually use */
2000  if (transport != JINGLE_TRANSPORT_NONE) {
2001  session->transport = transport;
2002  /* Note that for Google-V1 and Google-V2 we don't stop built-in ICE support, this will happen in jingle_new */
2003  }
2004 
2005  if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, target, assignedids, requestor, NULL))) {
2006  ast_log(LOG_ERROR, "Unable to create Jingle channel on endpoint '%s'\n", args.name);
2007  *cause = AST_CAUSE_SWITCH_CONGESTION;
2008  ao2_ref(session, -1);
2009  return NULL;
2010  }
2011 
2012  /* If video was requested try to enable it on the session */
2014  jingle_enable_video(session);
2015  }
2016 
2017  /* As this is outgoing set ourselves as controlling */
2018  if (session->rtp && (ice = ast_rtp_instance_get_ice(session->rtp))) {
2019  ice->ice_lite(session->rtp);
2020  }
2021 
2022  if (session->vrtp && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
2023  ice->ice_lite(session->vrtp);
2024  }
2025 
2026  /* We purposely don't decrement the session here as there is a reference on the channel */
2027  ao2_link(endpoint->state->sessions, session);
2028 
2029  return chan;
2030 }
Main Channel structure associated with a channel.
static struct jingle_session * jingle_alloc(struct jingle_endpoint *endpoint, const char *from, const char *sid)
Internal helper function used to allocate Jingle session on an endpoint.
Definition: chan_motif.c:701
static void jingle_enable_video(struct jingle_session *session)
Internal helper function which enables video support on a sesson if possible.
Definition: chan_motif.c:668
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
#define OBJ_KEY
Definition: astobj2.h:1155
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:2891
char resource[XMPP_MAX_RESJIDLEN]
Definition: xmpp.h:93
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
const char * args
#define NULL
Definition: resample.c:96
Session which contains information about an active session.
Definition: chan_motif.c:296
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
#define ast_log
Definition: astobj2.c:42
#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:851
static struct ast_mansession session
unsigned int google
Definition: xmpp.h:88
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct console_pvt globals
jingle_transport
The various transport methods supported, from highest priority to lowest priority when doing fallback...
Definition: chan_motif.c:262
XMPP Resource.
Definition: xmpp.h:92
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
static void * jingle_endpoint_find(struct ao2_container *tmp_container, const char *category)
Find function for Jingle endpoints.
Definition: chan_motif.c:460
#define LOG_ERROR
Definition: logger.h:285
struct ast_rtp_instance * vrtp
Definition: chan_motif.c:312
#define AST_CAUSE_CHANNEL_UNACCEPTABLE
Definition: causes.h:101
unsigned int jingle
Definition: xmpp.h:87
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
XMPP Buddy.
Definition: xmpp.h:112
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ao2_container * resources
Definition: xmpp.h:114
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
enum jingle_transport transport
Definition: chan_motif.c:304
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:484
struct ast_xmpp_capabilities caps
Definition: xmpp.h:97
static struct ast_channel * jingle_new(struct jingle_endpoint *endpoint, struct jingle_session *session, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
Function called to create a new Jingle Asterisk channel.
Definition: chan_motif.c:768
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:129
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type)
Find out if the capabilities structure has any formats of a specific type.
Definition: format_cap.c:615
#define AST_APP_ARG(name)
Define an application argument.
void(* ice_lite)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:500
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ jingle_send_error_response()

static void jingle_send_error_response ( struct ast_xmpp_client connection,
ikspak *  pak,
const char *  type,
const char *  reasonstr,
const char *  reasonstr2 
)
static

Internal helper function which sends an error response.

Definition at line 884 of file chan_motif.c.

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

Referenced by jingle_action_session_accept(), jingle_action_session_info(), jingle_action_session_initiate(), jingle_action_session_terminate(), and jingle_action_transport_info().

885 {
886  iks *response, *error = NULL, *reason = NULL, *reason2 = NULL;
887 
888  if (!(response = iks_new("iq")) ||
889  !(error = iks_new("error")) ||
890  !(reason = iks_new(reasonstr))) {
891  ast_log(LOG_ERROR, "Unable to allocate IKS error response stanzas\n");
892  goto end;
893  }
894 
895  iks_insert_attrib(response, "type", "error");
896  iks_insert_attrib(response, "from", connection->jid->full);
897  iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
898  iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
899 
900  iks_insert_attrib(error, "type", type);
901  iks_insert_node(error, reason);
902 
903  if (!ast_strlen_zero(reasonstr2) && (reason2 = iks_new(reasonstr2))) {
904  iks_insert_node(error, reason2);
905  }
906 
907  iks_insert_node(response, error);
908 
909  ast_xmpp_client_send(connection, response);
910 end:
911  iks_delete(reason2);
912  iks_delete(reason);
913  iks_delete(error);
914  iks_delete(response);
915 }
static const char type[]
Definition: chan_ooh323.c:109
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
Definition: res_xmpp.c:2534
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define ast_strlen_zero(a)
Definition: muted.c:73
iksid * jid
Definition: xmpp.h:126
int error(const char *format,...)
Definition: utils/frame.c:999

◆ jingle_send_response()

static void jingle_send_response ( struct ast_xmpp_client connection,
ikspak *  pak 
)
static

Internal helper function which sends a response.

Definition at line 864 of file chan_motif.c.

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

Referenced by jingle_action_session_accept(), jingle_action_session_info(), jingle_action_session_initiate(), jingle_action_session_terminate(), and jingle_action_transport_info().

865 {
866  iks *response;
867 
868  if (!(response = iks_new("iq"))) {
869  ast_log(LOG_ERROR, "Unable to allocate an IKS response stanza\n");
870  return;
871  }
872 
873  iks_insert_attrib(response, "type", "result");
874  iks_insert_attrib(response, "from", connection->jid->full);
875  iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
876  iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
877 
878  ast_xmpp_client_send(connection, response);
879 
880  iks_delete(response);
881 }
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
Definition: res_xmpp.c:2534
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
iksid * jid
Definition: xmpp.h:126

◆ jingle_send_session_accept()

static void jingle_send_session_accept ( struct jingle_session session)
static

Internal function which sends a session-accept message.

Definition at line 1518 of file chan_motif.c.

References jingle_send_session_action(), JINGLE_TRANSPORT_GOOGLE_V1, and jingle_session::transport.

Referenced by jingle_answer().

1519 {
1520  jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "accept" : "session-accept");
1521 }
enum jingle_transport transport
Definition: chan_motif.c:304
static void jingle_send_session_action(struct jingle_session *session, const char *action)
Internal function which sends a complete session message.
Definition: chan_motif.c:1430

◆ jingle_send_session_action()

static void jingle_send_session_action ( struct jingle_session session,
const char *  action 
)
static

Internal function which sends a complete session message.

Definition at line 1430 of file chan_motif.c.

References AST_CAUSE_SWITCH_CONGESTION, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_xmpp_client_send(), ast_xmpp_increment_mid(), jingle_session::audio_name, jingle_session::connection, GOOGLE_SESSION_NS, ast_xmpp_client::jid, jingle_add_content(), JINGLE_NS, jingle_queue_hangup_with_cause(), JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, jingle_session::maxpayloads, ast_xmpp_client::mid, NULL, jingle_session::outgoing, jingle_session::remote, jingle_session::rtp, jingle_session::sid, jingle_session::transport, jingle_session::video_name, and jingle_session::vrtp.

Referenced by jingle_send_session_accept(), and jingle_send_session_initiate().

1431 {
1432  iks *iq, *jingle, *audio = NULL, *audio_description = NULL, *video = NULL, *video_description = NULL;
1433  iks *audio_payloads[session->maxpayloads], *video_payloads[session->maxpayloads];
1434  iks *audio_transport = NULL, *video_transport = NULL;
1435  int i, res = 0;
1436 
1437  if (!(iq = iks_new("iq")) ||
1438  !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
1440  iks_delete(iq);
1441  return;
1442  }
1443 
1444  memset(audio_payloads, 0, sizeof(audio_payloads));
1445  memset(video_payloads, 0, sizeof(video_payloads));
1446 
1447  iks_insert_attrib(iq, "from", session->connection->jid->full);
1448  iks_insert_attrib(iq, "to", session->remote);
1449  iks_insert_attrib(iq, "type", "set");
1450  iks_insert_attrib(iq, "id", session->connection->mid);
1452 
1453  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1454  iks_insert_attrib(jingle, "type", action);
1455  iks_insert_attrib(jingle, "id", session->sid);
1456  iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1457  } else {
1458  iks_insert_attrib(jingle, "action", action);
1459  iks_insert_attrib(jingle, "sid", session->sid);
1460  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1461  }
1462 
1463  if (!strcasecmp(action, "session-initiate") || !strcasecmp(action, "initiate") || !strcasecmp(action, "accept")) {
1464  iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
1465  }
1466 
1467  iks_insert_node(iq, jingle);
1468 
1469  if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) &&
1470  (audio_transport = iks_new("transport"))) {
1471  res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name,
1472  AST_MEDIA_TYPE_AUDIO, session->rtp, audio_payloads);
1473  } else {
1474  ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid);
1475  res = -1;
1476  }
1477 
1478  if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
1479  if ((video = iks_new("content")) && (video_description = iks_new("description")) &&
1480  (video_transport = iks_new("transport"))) {
1481  res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name,
1482  AST_MEDIA_TYPE_VIDEO, session->vrtp, video_payloads);
1483  } else {
1484  ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid);
1485  res = -1;
1486  }
1487  }
1488 
1489  if (!res) {
1490  ast_xmpp_client_send(session->connection, iq);
1491  } else {
1493  }
1494 
1495  iks_delete(video_transport);
1496  iks_delete(audio_transport);
1497 
1498  for (i = 0; i < session->maxpayloads; i++) {
1499  iks_delete(video_payloads[i]);
1500  iks_delete(audio_payloads[i]);
1501  }
1502 
1503  iks_delete(video_description);
1504  iks_delete(video);
1505  iks_delete(audio_description);
1506  iks_delete(audio);
1507  iks_delete(jingle);
1508  iks_delete(iq);
1509 }
const ast_string_field audio_name
Definition: chan_motif.c:301
const ast_string_field sid
Definition: chan_motif.c:301
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
#define NULL
Definition: resample.c:96
struct ast_rtp_instance * rtp
Definition: chan_motif.c:311
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
Definition: res_xmpp.c:2534
unsigned int outgoing
Definition: chan_motif.c:316
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1016
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
Definition: chan_motif.c:1197
struct ast_rtp_instance * vrtp
Definition: chan_motif.c:312
struct ast_xmpp_client * connection
Definition: chan_motif.c:303
char remote[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:308
static int jingle_add_content(struct jingle_session *session, iks *jingle, iks *content, iks *description, iks *transport, const char *name, enum ast_media_type type, struct ast_rtp_instance *rtp, iks **payloads)
Helper function which adds content to a description.
Definition: chan_motif.c:1392
iksid * jid
Definition: xmpp.h:126
enum jingle_transport transport
Definition: chan_motif.c:304
char mid[6]
Definition: xmpp.h:125
unsigned int maxpayloads
Definition: chan_motif.c:306
#define GOOGLE_SESSION_NS
Namespace for Google Session.
Definition: chan_motif.c:250
const ast_string_field video_name
Definition: chan_motif.c:301
#define JINGLE_NS
Namespace for Jingle itself.
Definition: chan_motif.c:232

◆ jingle_send_session_info()

static void jingle_send_session_info ( struct jingle_session session,
const char *  info 
)
static

Internal function which sends a session-info message.

Definition at line 1098 of file chan_motif.c.

References ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), jingle_session::connection, end, JINGLE_NS, JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, ast_xmpp_client::mid, NULL, jingle_session::remote, jingle_session::sid, text, and jingle_session::transport.

Referenced by jingle_indicate().

1099 {
1100  iks *iq = NULL, *jingle = NULL, *text = NULL;
1101 
1102  /* Google-V1 has no way to send informational messages so don't even bother trying */
1103  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1104  return;
1105  }
1106 
1107  if (!(iq = iks_new("iq")) || !(jingle = iks_new("jingle")) || !(text = iks_new(info))) {
1108  ast_log(LOG_ERROR, "Failed to allocate stanzas for session-info message on session '%s'\n", session->sid);
1109  goto end;
1110  }
1111 
1112  iks_insert_attrib(iq, "to", session->remote);
1113  iks_insert_attrib(iq, "type", "set");
1114  iks_insert_attrib(iq, "id", session->connection->mid);
1116 
1117  iks_insert_attrib(jingle, "action", "session-info");
1118  iks_insert_attrib(jingle, "sid", session->sid);
1119  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1120  iks_insert_node(iq, jingle);
1121  iks_insert_node(jingle, text);
1122 
1123  ast_xmpp_client_send(session->connection, iq);
1124 
1125 end:
1126  iks_delete(text);
1127  iks_delete(jingle);
1128  iks_delete(iq);
1129 }
const ast_string_field sid
Definition: chan_motif.c:301
char * text
Definition: app_queue.c:1511
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
Definition: res_xmpp.c:2534
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1016
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
def info(msg)
struct ast_xmpp_client * connection
Definition: chan_motif.c:303
char remote[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:308
enum jingle_transport transport
Definition: chan_motif.c:304
char mid[6]
Definition: xmpp.h:125
#define JINGLE_NS
Namespace for Jingle itself.
Definition: chan_motif.c:232

◆ jingle_send_session_initiate()

static void jingle_send_session_initiate ( struct jingle_session session)
static

Internal function which sends a session-inititate message.

Definition at line 1512 of file chan_motif.c.

References jingle_send_session_action(), JINGLE_TRANSPORT_GOOGLE_V1, and jingle_session::transport.

Referenced by jingle_call(), and jingle_outgoing_hook().

1513 {
1514  jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "initiate" : "session-initiate");
1515 }
enum jingle_transport transport
Definition: chan_motif.c:304
static void jingle_send_session_action(struct jingle_session *session, const char *action)
Internal function which sends a complete session message.
Definition: chan_motif.c:1430

◆ jingle_send_session_terminate()

static void jingle_send_session_terminate ( struct jingle_session session,
const char *  reasontext 
)
static

Internal function which sends a session-terminate message.

Definition at line 1058 of file chan_motif.c.

References ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), jingle_session::connection, end, GOOGLE_SESSION_NS, ast_xmpp_client::jid, JINGLE_NS, JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, ast_xmpp_client::mid, NULL, jingle_session::outgoing, jingle_session::remote, jingle_session::sid, text, and jingle_session::transport.

Referenced by jingle_hangup().

1059 {
1060  iks *iq = NULL, *jingle = NULL, *reason = NULL, *text = NULL;
1061 
1062  if (!(iq = iks_new("iq")) || !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle")) ||
1063  !(reason = iks_new("reason")) || !(text = iks_new(reasontext))) {
1064  ast_log(LOG_ERROR, "Failed to allocate stanzas for session-terminate message on session '%s'\n", session->sid);
1065  goto end;
1066  }
1067 
1068  iks_insert_attrib(iq, "to", session->remote);
1069  iks_insert_attrib(iq, "type", "set");
1070  iks_insert_attrib(iq, "id", session->connection->mid);
1072 
1073  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1074  iks_insert_attrib(jingle, "type", "terminate");
1075  iks_insert_attrib(jingle, "id", session->sid);
1076  iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1077  iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
1078  } else {
1079  iks_insert_attrib(jingle, "action", "session-terminate");
1080  iks_insert_attrib(jingle, "sid", session->sid);
1081  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1082  }
1083 
1084  iks_insert_node(iq, jingle);
1085  iks_insert_node(jingle, reason);
1086  iks_insert_node(reason, text);
1087 
1088  ast_xmpp_client_send(session->connection, iq);
1089 
1090 end:
1091  iks_delete(text);
1092  iks_delete(reason);
1093  iks_delete(jingle);
1094  iks_delete(iq);
1095 }
const ast_string_field sid
Definition: chan_motif.c:301
char * text
Definition: app_queue.c:1511
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
Definition: res_xmpp.c:2534
unsigned int outgoing
Definition: chan_motif.c:316
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1016
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
struct ast_xmpp_client * connection
Definition: chan_motif.c:303
char remote[XMPP_MAX_JIDLEN]
Definition: chan_motif.c:308
iksid * jid
Definition: xmpp.h:126
enum jingle_transport transport
Definition: chan_motif.c:304
char mid[6]
Definition: xmpp.h:125
#define GOOGLE_SESSION_NS
Namespace for Google Session.
Definition: chan_motif.c:250
#define JINGLE_NS
Namespace for Jingle itself.
Definition: chan_motif.c:232

◆ jingle_send_transport_info()

static void jingle_send_transport_info ( struct jingle_session session,
const char *  from 
)
static

Internal function which sends a transport-info message.

Definition at line 1211 of file chan_motif.c.

References AST_CAUSE_SWITCH_CONGESTION, ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), jingle_session::audio_name, jingle_session::connection, GOOGLE_SESSION_NS, ast_xmpp_client::jid, jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), JINGLE_NS, jingle_queue_hangup_with_cause(), JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, JINGLE_TRANSPORT_ICE_UDP, LOG_ERROR, jingle_session::maxicecandidates, ast_xmpp_client::mid, NULL, jingle_session::outgoing, jingle_session::rtp, jingle_session::sid, jingle_session::transport, jingle_session::video_name, and jingle_session::vrtp.

Referenced by jingle_action_session_initiate(), and jingle_outgoing_hook().

1212 {
1213  iks *iq, *jingle = NULL, *audio = NULL, *audio_transport = NULL, *video = NULL, *video_transport = NULL;
1214  iks *audio_candidates[session->maxicecandidates], *video_candidates[session->maxicecandidates];
1215  int i, res = 0;
1216 
1217  if (!(iq = iks_new("iq")) ||
1218  !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
1219  iks_delete(iq);
1221  ast_log(LOG_ERROR, "Failed to allocate stanzas for transport-info message, hanging up session '%s'\n", session->sid);
1222  return;
1223  }
1224 
1225  memset(audio_candidates, 0, sizeof(audio_candidates));
1226  memset(video_candidates, 0, sizeof(video_candidates));
1227 
1228  iks_insert_attrib(iq, "from", session->connection->jid->full);
1229  iks_insert_attrib(iq, "to", from);
1230  iks_insert_attrib(iq, "type", "set");
1231  iks_insert_attrib(iq, "id", session->connection->mid);
1233 
1234  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1235  iks_insert_attrib(jingle, "type", "candidates");
1236  iks_insert_attrib(jingle, "id", session->sid);
1237  iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1238  iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : from);
1239  } else {
1240  iks_insert_attrib(jingle, "action", "transport-info");
1241  iks_insert_attrib(jingle, "sid", session->sid);
1242  iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1243  }
1244  iks_insert_node(iq, jingle);
1245 
1246  if (session->rtp) {
1247  if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1248  /* V1 protocol has the candidates directly in the session */
1249  res = jingle_add_google_candidates_to_transport(session->rtp, jingle, audio_candidates, 0, session->transport, session->maxicecandidates);
1250  } else if ((audio = iks_new("content")) && (audio_transport = iks_new("transport"))) {
1251  iks_insert_attrib(audio, "creator", session->outgoing ? "initiator" : "responder");
1252  iks_insert_attrib(audio, "name", session->audio_name);
1253  iks_insert_node(jingle, audio);
1254  iks_insert_node(audio, audio_transport);
1255 
1256  if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1257  res = jingle_add_ice_udp_candidates_to_transport(session->rtp, audio_transport, audio_candidates, session->maxicecandidates);
1258  } else if (session->transport ==