Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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"
Include dependency graph for chan_motif.c:

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)
 Asterisk core interaction functions. 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.

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

◆ ENDPOINT_BUCKETS

#define ENDPOINT_BUCKETS   37

Number of buckets for endpoints.

Definition at line 226 of file chan_motif.c.

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

◆ GOOGLE_SESSION_NS

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

Namespace for Google Session.

Definition at line 250 of file chan_motif.c.

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

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

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

◆ JINGLE_NS

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

Namespace for Jingle itself.

Definition at line 232 of file chan_motif.c.

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

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

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

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

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};
@ JINGLE_TRANSPORT_ICE_UDP
Definition: chan_motif.c:263
@ JINGLE_TRANSPORT_GOOGLE_V1
Definition: chan_motif.c:265
@ JINGLE_TRANSPORT_NONE
Definition: chan_motif.c:266
@ JINGLE_TRANSPORT_GOOGLE_V2
Definition: chan_motif.c:264

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

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

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}
#define var
Definition: ast_expr2f.c:605
#define ast_log
Definition: astobj2.c:42
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
#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
#define LOG_ERROR
iksfilter * filter
Definition: xmpp.h:128
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:275
iksrule * rule
Definition: chan_motif.c:285
struct ast_xmpp_client * connection
Definition: chan_motif.c:284
const ast_string_field name
Definition: chan_motif.c:283
struct ast_xmpp_client * ast_xmpp_client_find(const char *name)
Find an XMPP client connection using a given name.
Definition: res_xmpp.c:881

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

Referenced by load_module().

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

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 ast_get_group(const char *s)
Definition: channel.c:7618
ast_group_t pickupgroup
Definition: chan_motif.c:290
ast_group_t callgroup
Definition: chan_motif.c:289

References ast_get_group(), jingle_endpoint::callgroup, jingle_endpoint::pickupgroup, and var.

Referenced by load_module().

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

2700{
2701 struct jingle_endpoint *endpoint = obj;
2702
2703 if (!strcasecmp(var->value, "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);
2712 }
2713
2714 return 0;
2715}
#define LOG_WARNING
enum jingle_transport transport
Definition: chan_motif.c:291

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

Referenced by load_module().

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

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}
static struct ast_mansession session
#define OBJ_KEY
Definition: astobj2.h:1151
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static const struct jingle_action_handler jingle_action_handlers[]
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2308
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:2327
#define LOG_NOTICE
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void(* handler)(struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
Definition: chan_motif.c:375
struct ao2_container * sessions
Definition: chan_motif.c:271
struct jingle_endpoint_state * state
Definition: chan_motif.c:292
Session which contains information about an active session.
Definition: chan_motif.c:296
#define ARRAY_LEN(a)
Definition: utils.h:666

References ao2_find, ao2_ref, ARRAY_LEN, ast_callid_threadassoc_add(), ast_callid_threadassoc_remove(), ast_log, ast_strlen_zero(), 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().

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

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
2486
2487 if ((chan = jingle_session_lock_full(session))) {
2489 ast_channel_unlock(chan);
2490 ast_channel_unref(chan);
2491 }
2493
2494 jingle_send_response(endpoint->connection, pak);
2495}
#define ao2_unlock(a)
Definition: astobj2.h:729
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1148
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
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 void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:864
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define ast_channel_unlock(chan)
Definition: channel.h:2923
@ AST_CONTROL_ANSWER
Main Channel structure associated with a channel.

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(), jingle_session_lock_full(), and session.

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

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))) {
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);
2528
2529 jingle_send_response(endpoint->connection, pak);
2530}
#define JINGLE_RTP_INFO_NS
Namespace for Jingle RTP info.
Definition: chan_motif.c:238
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
@ AST_CONTROL_RINGING

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(), NULL, and session.

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

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 ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
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
jingle_transport
The various transport methods supported, from highest priority to lowest priority when doing fallback...
Definition: chan_motif.c:262
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_transport_info(struct jingle_session *session, const char *from)
Internal function which sends a transport-info message.
Definition: chan_motif.c:1211
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#define ast_channel_lock(chan)
Definition: channel.h:2922
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_PBX_FAILED
Definition: pbx.h:372
@ AST_PBX_CALL_LIMIT
Definition: pbx.h:373
@ AST_PBX_SUCCESS
Definition: pbx.h:371
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708

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_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, session, jingle_endpoint_state::sessions, and jingle_endpoint::state.

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

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))) {
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);
2590
2591 jingle_send_response(endpoint->connection, pak);
2592}
char * text
Definition: app_queue.c:1639
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define AST_CAUSE_NORMAL
Definition: causes.h:151
static const struct jingle_reason_mapping jingle_reason_mappings[]
const char * ast_channel_name(const struct ast_channel *chan)
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:1238
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
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:4346
#define AST_CHANNEL_NAME
Definition: channel.h:171
@ AST_CONTROL_PVT_CAUSE_CODE
#define ast_debug(level,...)
Log a DEBUG message.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char chan_name[AST_CHANNEL_NAME]

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_reason_mappings, jingle_send_error_response(), jingle_send_response(), jingle_session_lock_full(), session, and text.

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

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
2470 jingle_send_response(endpoint->connection, pak);
2471}

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

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

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 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
#define GOOGLE_PHONE_NS
Namespace for Google Phone description.
Definition: chan_motif.c:253
#define JINGLE_RTP_NS
Namespace for Jingle RTP sessions.
Definition: chan_motif.c:235
#define GOOGLE_TRANSPORT_NS
Namespace for Google Talk ICE-UDP.
Definition: chan_motif.c:244
#define JINGLE_ICE_UDP_NS
Namespace for Jingle ICE-UDP.
Definition: chan_motif.c:241
static const char type[]
Definition: chan_ooh323.c:109
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
static const char name[]
Definition: format_mp3.c:68

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, name, session, and type.

Referenced by jingle_send_session_action().

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

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
1052 ao2_ref(local_candidates, -1);
1053
1054 return res;
1055}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:327
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:358
@ AST_RTP_ICE_CANDIDATE_TYPE_SRFLX
Definition: rtp_engine.h:503
@ AST_RTP_ICE_CANDIDATE_TYPE_HOST
Definition: rtp_engine.h:502
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:2928
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure for an ICE candidate.
Definition: rtp_engine.h:520
struct ast_sockaddr address
Definition: rtp_engine.h:525
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:522
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:527
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:531
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:541
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:543
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:545

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, ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

Referenced by jingle_send_transport_info().

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

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}
static int tmp()
Definition: bt_open.c:389
@ AST_RTP_ICE_CANDIDATE_TYPE_RELAYED
Definition: rtp_engine.h:504
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259
long int ast_random(void)
Definition: utils.c:2312

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(), ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

Referenced by jingle_send_transport_info().

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

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}
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
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
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:106
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
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
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:2035
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:2005
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:748
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:1886
Definition of a media format.
Definition: format.c:43

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(), GOOGLE_PHONE_NS, JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, session, tmp(), type, and ast_channel::x.

Referenced by jingle_add_content().

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

702{
703 struct jingle_session *session;
705 struct ast_sockaddr tmp;
706
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}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static void jingle_session_destructor(void *obj)
Destructor for Jingle sessions.
Definition: chan_motif.c:561
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
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 ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2286
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:2281
unsigned int ast_callid
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_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:486
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:726
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:123
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:117
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
Socket address structure.
Definition: netsock2.h:97
unsigned int maxpayloads
Definition: chan_motif.c:287
unsigned int maxicecandidates
Definition: chan_motif.c:286
struct ast_format_cap * cap
Definition: chan_motif.c:288
ast_callid callid
Definition: chan_motif.c:318
Definition: sched.c:76

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_endpoint::connection, jingle_session_destructor(), jingle_endpoint::maxicecandidates, jingle_endpoint::maxpayloads, NULL, session, jingle_endpoint::state, tmp(), and jingle_endpoint::transport.

Referenced by jingle_action_session_initiate(), and jingle_request().

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

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
1635
1636 return 0;
1637}
static void jingle_send_session_accept(struct jingle_session *session)
Internal function which sends a session-accept message.
Definition: chan_motif.c:1518
void * ast_channel_tech_pvt(const struct ast_channel *chan)

References ast_channel_tech_pvt(), AST_STATE_UP, jingle_send_session_accept(), and 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.

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}
static void jingle_send_session_initiate(struct jingle_session *session)
Internal function which sends a session-inititate message.
Definition: chan_motif.c:1512
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

References ast_channel_tech_pvt(), ast_format_cap_append_from_cap(), AST_MEDIA_TYPE_UNKNOWN, ast_setstate(), AST_STATE_RING, jingle_outgoing_hook(), jingle_send_session_initiate(), and session.

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

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}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static void jingle_config_destructor(void *obj)
Destructor called when module configuration goes away.
Definition: chan_motif.c:591
static int jingle_endpoint_cmp(void *obj, void *arg, int flags)
Comparator function for Jingle endpoints.
Definition: chan_motif.c:535
#define ENDPOINT_BUCKETS
Number of buckets for endpoints.
Definition: chan_motif.c:226
static int jingle_endpoint_hash(const void *obj, const int flags)
Hashing function for Jingle endpoints.
Definition: chan_motif.c:526
struct ao2_container * endpoints
Definition: chan_motif.c:324

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

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

592{
593 struct jingle_config *cfg = obj;
595}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934

References ao2_cleanup, and jingle_config::endpoints.

Referenced by jingle_config_alloc().

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

1827{
1829
1830 if (session->rtp) {
1832 }
1833
1834 return 0;
1835}
char digit
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
Definition: rtp_engine.c:2094

References ast_channel_tech_pvt(), ast_rtp_instance_dtmf_begin(), digit, and session.

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

1839{
1841
1842 if (session->rtp) {
1844 }
1845
1846 return 0;
1847}
int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
Definition: rtp_engine.c:2122

References ast_channel_tech_pvt(), ast_rtp_instance_dtmf_end_with_duration(), digit, and session.

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

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
695 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
696 ice->stop(session->vrtp);
697 }
698}
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2426
unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
Get the global framing.
Definition: format_cap.c:438
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:613
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:1571
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:574
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:2205
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:539

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_TRANSPORT_GOOGLE_V2, NULL, session, ast_rtp_engine_ice::stop, and tmp().

Referenced by jingle_interpret_description(), and jingle_request().

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

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
static struct jingle_endpoint_state * jingle_endpoint_state_find_or_create(const char *category)
State find/create function.
Definition: chan_motif.c:485

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.

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

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}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028

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

Referenced by jingle_config_alloc().

◆ jingle_endpoint_destructor()

static void jingle_endpoint_destructor ( void *  obj)
static

Destructor for Jingle endpoints.

Definition at line 441 of file chan_motif.c.

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}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
void ast_xmpp_client_unref(struct ast_xmpp_client *client)
Release XMPP client connection reference.
Definition: res_xmpp.c:894

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

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

461{
462 return ao2_find(tmp_container, category, OBJ_KEY);
463}

References ao2_find, and OBJ_KEY.

Referenced by jingle_endpoint_state_find_or_create(), and jingle_request().

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

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}

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

Referenced by jingle_config_alloc().

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

467{
469
471 return NULL;
472 }
473
476 if (!state->sessions) {
477 ao2_ref(state, -1);
478 return NULL;
479 }
480
481 return state;
482}
enum cc_state state
Definition: ccss.c:393
#define SESSION_BUCKETS
Number of buckets for sessions, on a per-endpoint basis.
Definition: chan_motif.c:229
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
static int jingle_session_cmp(void *obj, void *arg, int flags)
Comparator function for Jingle sessions.
Definition: chan_motif.c:424
Endpoint state information.
Definition: chan_motif.c:270

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, and state.

Referenced by jingle_endpoint_state_find_or_create().

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

434{
435 struct jingle_endpoint_state *state = obj;
436
437 ao2_ref(state->sessions, -1);
438}

References ao2_ref.

Referenced by jingle_endpoint_state_create().

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

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)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
static struct console_pvt globals
static void * jingle_endpoint_find(struct ao2_container *tmp_container, const char *category)
Find function for Jingle endpoints.
Definition: chan_motif.c:460
static struct jingle_endpoint_state * jingle_endpoint_state_create(void)
Allocator function for Jingle endpoint state.
Definition: chan_motif.c:466
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

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

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

1736{
1737 struct jingle_session *session = ast_channel_tech_pvt(newchan);
1738
1740
1741 jingle_set_owner(session, newchan);
1742
1744
1745 return 0;
1746}
#define ao2_lock(a)
Definition: astobj2.h:717
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

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

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

622{
625
626 if (!session->rtp) {
628 }
629
630 ao2_ref(session->rtp, +1);
631 *instance = session->rtp;
632
633 return res;
634}
ast_rtp_glue_result
Definition: rtp_engine.h:158
@ AST_RTP_GLUE_RESULT_LOCAL
Definition: rtp_engine.h:164
@ AST_RTP_GLUE_RESULT_FORBID
Definition: rtp_engine.h:160

References ao2_ref, ast_channel_tech_pvt(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, and session.

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

1870{
1872
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
1889 }
1890
1893
1894 ao2_unlink(session->state->sessions, session);
1895 ao2_ref(session->state, -1);
1896
1898 ao2_ref(session, -1);
1899
1900 return 0;
1901}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
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
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
int ast_channel_hangupcause(const struct ast_channel *chan)
const char * reason
Definition: chan_motif.c:393

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_reason_mappings, jingle_send_session_terminate(), jingle_set_owner(), NULL, jingle_reason_mapping::reason, and session.

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

1750{
1752 int res = 0;
1753
1754 switch (condition) {
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;
1791 if (session->rtp) {
1793 }
1794 break;
1796 if (session->rtp) {
1798 }
1799 break;
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}
#define AST_CAUSE_BUSY
Definition: causes.h:149
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
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_HOLD
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_SRCCHANGE
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_MASQUERADE_NOTIFY
@ AST_CONTROL_UPDATE_RTP_PEER
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:7766
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
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:2173
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:2164

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, and session.

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

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 associating 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) {
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 }
2385
2386 return 0;
2387}
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:123
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:130
#define AST_CAUSE_FACILITY_NOT_IMPLEMENTED
Definition: causes.h:133
#define GOOGLE_VIDEO_NS
Namespace for Google Video description.
Definition: chan_motif.c:256
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
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
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
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
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5762
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5803
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54

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(), 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, LOG_ERROR, name, NULL, and session.

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

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

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
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}
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
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
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:628
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:523
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:995
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:1237
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:1593
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:979
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:1441
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:1356

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(), codecs, ast_xmpp_resource::description, jingle_enable_video(), jingle_queue_hangup_with_cause(), JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, name, NULL, and session.

Referenced by jingle_interpret_content().

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

2202{
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) ||
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 }
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:145
char * address
Definition: f2c.h:59
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
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:2698

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, session, and ast_rtp_engine_ice::stop.

Referenced by jingle_interpret_content().

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

2121{
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) ||
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}
static int priority
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
int ast_sockaddr_is_ipv4(const struct ast_sockaddr *addr)
Determine if the address is an IPv4 address.
Definition: netsock2.c:497
#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:1238
#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:1126
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:533
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:537
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:535

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, session, ast_rtp_engine_ice::set_authentication, ast_rtp_engine_ice::start, ast_rtp_engine_ice_candidate::transport, type, and ast_rtp_engine_ice_candidate::type.

Referenced by jingle_interpret_content().

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

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
794
795 ast_channel_callid_set(chan, session->callid);
796
799 ao2_ref(caps, -1);
800
801 if (session->rtp) {
802 struct ast_rtp_engine_ice *ice;
803
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);
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 }
854
855 ao2_unlock(endpoint);
856
858 ast_channel_unlock(chan);
859
860 return chan;
861}
const char * str
Definition: app_jack.c:147
static struct ast_channel_tech jingle_tech
PBX interface structure for channel registration.
Definition: chan_motif.c:353
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
void ast_channel_rings_set(struct ast_channel *chan, int value)
#define ast_channel_alloc_with_endpoint(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, endpoint,...)
Definition: channel.h:1262
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:871
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
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:4175
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
struct ast_endpoint * endpoint
Definition: xmpp.h:148
const ast_string_field language
Definition: chan_motif.c:283
const ast_string_field musicclass
Definition: chan_motif.c:283
const ast_string_field accountcode
Definition: chan_motif.c:283
const ast_string_field context
Definition: chan_motif.c:283

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_endpoint::connection, jingle_endpoint::context, ast_xmpp_client::endpoint, jingle_set_owner(), jingle_tech, JINGLE_TRANSPORT_GOOGLE_V1, JINGLE_TRANSPORT_GOOGLE_V2, jingle_endpoint::language, jingle_endpoint::musicclass, jingle_endpoint::name, NULL, jingle_endpoint::pickupgroup, S_OR, session, ast_rtp_engine_ice::stop, and str.

Referenced by jingle_action_session_initiate(), and jingle_request().

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

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 }
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
1618end:
1620
1621 return IKS_FILTER_EAT;
1622}
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:125
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:100
#define XMPP_STANZAS_NS
Namespace for XMPP stanzas.
Definition: chan_motif.c:259
char * end
Definition: eagi_proxy.c:73
@ AST_CONTROL_PROCEEDING
int error(const char *format,...)
Definition: utils/frame.c:999

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(), end, error(), jingle_outgoing_hook(), 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, NULL, session, ast_rtp_engine_ice::stop, and XMPP_STANZAS_NS.

Referenced by jingle_call(), and jingle_outgoing_hook().

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

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 }
1208}

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

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

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

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);
1687 ao2_ref(caps, -1);
1688 }
1691 }
1692 }
1693
1694 return frame;
1695}
int ast_channel_fdno(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
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:581
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_frfree(fr)
@ AST_FRAME_VOICE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:599
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype

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, session, and ast_frame::subclass.

◆ 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

Asterisk core interaction functions.

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

Definition at line 1904 of file chan_motif.c.

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;
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);
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;
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 }
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);
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);
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);
2008 ao2_ref(session, -1);
2009 return NULL;
2010 }
2011
2012 /* If video was requested try to enable it on the 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}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define AST_CAUSE_CHANNEL_UNACCEPTABLE
Definition: causes.h:102
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
void(* ice_lite)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:547
XMPP Buddy.
Definition: xmpp.h:112
struct ao2_container * resources
Definition: xmpp.h:114
XMPP Resource.
Definition: xmpp.h:92
char resource[XMPP_MAX_RESJIDLEN]
Definition: xmpp.h:93
const char * args

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_channel::dialed, globals, ast_rtp_engine_ice::ice_lite, 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, and session.

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

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);
910end:
911 iks_delete(reason2);
912 iks_delete(reason);
913 iks_delete(error);
914 iks_delete(response);
915}
iksid * jid
Definition: xmpp.h:126
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

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

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

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

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}

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

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

1519{
1520 jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "accept" : "session-accept");
1521}
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

References jingle_send_session_action(), JINGLE_TRANSPORT_GOOGLE_V1, and session.

Referenced by jingle_answer().

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

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);
1451 ast_xmpp_increment_mid(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}
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
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1025

References AST_CAUSE_SWITCH_CONGESTION, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_xmpp_client_send(), ast_xmpp_increment_mid(), GOOGLE_SESSION_NS, jingle_add_content(), JINGLE_NS, jingle_queue_hangup_with_cause(), JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, NULL, and session.

Referenced by jingle_send_session_accept(), and jingle_send_session_initiate().

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

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);
1115 ast_xmpp_increment_mid(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
1125end:
1126 iks_delete(text);
1127 iks_delete(jingle);
1128 iks_delete(iq);
1129}
def info(msg)

References ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), end, sip_to_pjsip::info(), JINGLE_NS, JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, NULL, session, and text.

Referenced by jingle_indicate().

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

1513{
1514 jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "initiate" : "session-initiate");
1515}

References jingle_send_session_action(), JINGLE_TRANSPORT_GOOGLE_V1, and session.

Referenced by jingle_call(), and jingle_outgoing_hook().

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

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);
1071 ast_xmpp_increment_mid(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
1090end:
1091 iks_delete(text);
1092 iks_delete(reason);
1093 iks_delete(jingle);
1094 iks_delete(iq);
1095}

References ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), end, GOOGLE_SESSION_NS, JINGLE_NS, JINGLE_TRANSPORT_GOOGLE_V1, LOG_ERROR, NULL, session, and text.

Referenced by jingle_hangup().

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

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);
1232 ast_xmpp_increment_mid(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 == JINGLE_TRANSPORT_GOOGLE_V2) {
1259 res = jingle_add_google_candidates_to_transport(session->rtp, audio_transport, audio_candidates, 0, session->transport,
1260 session->maxicecandidates);
1261 }
1262 } else {
1263 res = -1;
1264 }
1265 }
1266
1267 if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
1268 if ((video = iks_new("content")) && (video_transport = iks_new("transport"))) {
1269 iks_insert_attrib(video, "creator", session->outgoing ? "initiator" : "responder");
1270 iks_insert_attrib(video, "name", session->video_name);
1271 iks_insert_node(jingle, video);
1272 iks_insert_node(video, video_transport);
1273
1274 if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1275 res = jingle_add_ice_udp_candidates_to_transport(session->vrtp, video_transport, video_candidates, session->maxicecandidates);
1276 } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1277 res = jingle_add_google_candidates_to_transport(session->vrtp, video_transport, video_candidates, 1, session->transport,
1278 session->maxicecandidates);
1279 }
1280 } else {
1281 res = -1;
1282 }
1283 }
1284
1285 if (!res) {
1286 ast_xmpp_client_send(session->connection, iq);
1287 } else {
1289 }
1290
1291 /* Clean up after ourselves */
1292 for (i = 0; i < session->maxicecandidates; i++) {
1293 iks_delete(video_candidates[i]);
1294 iks_delete(audio_candidates[i]);
1295 }
1296
1297 iks_delete(video_transport);
1298 iks_delete(video);
1299 iks_delete(audio_transport);
1300 iks_delete(audio);
1301 iks_delete(jingle);
1302 iks_delete(iq);
1303}
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.
Definition: chan_motif.c:980
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.
Definition: chan_motif.c:918

References AST_CAUSE_SWITCH_CONGESTION, ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), GOOGLE_SESSION_NS, 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, NULL, and session.

Referenced by jingle_action_session_initiate(), and jingle_outgoing_hook().

◆ jingle_sendtext()

static int jingle_sendtext ( struct ast_channel ast,
const char *  text 
)
static

Function called by core to send text to the remote party of the Jingle session.

Definition at line 1818 of file chan_motif.c.

1819{
1821
1822 return ast_xmpp_client_send_message(session->connection, session->remote, text);
1823}
int ast_xmpp_client_send_message(struct ast_xmpp_client *client, const char *user, const char *message)
Send a message to a given user using an established XMPP client connection.
Definition: res_xmpp.c:938

References ast_channel_tech_pvt(), ast_xmpp_client_send_message(), session, and text.

◆ jingle_session_cmp()

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

Comparator function for Jingle sessions.

Definition at line 424 of file chan_motif.c.

425{
426 struct jingle_session *session1 = obj, *session2 = arg;
427 const char *sid = arg;
428
429 return !strcmp(session1->sid, flags & OBJ_KEY ? sid : session2->sid) ? CMP_MATCH | CMP_STOP : 0;
430}
const ast_string_field sid
Definition: chan_motif.c:301

References CMP_MATCH, CMP_STOP, OBJ_KEY, and jingle_session::sid.

Referenced by jingle_endpoint_state_create().

◆ jingle_session_destructor()

static void jingle_session_destructor ( void *  obj)
static

Destructor for Jingle sessions.

Definition at line 561 of file chan_motif.c.

562{
563 struct jingle_session *session = obj;
564
565 if (session->rule) {
566 iks_filter_remove_rule(session->connection->filter, session->rule);
567 }
568
569 if (session->connection) {
570 ast_xmpp_client_unref(session->connection);
571 }
572
573 if (session->rtp) {
576 }
577
578 if (session->vrtp) {
581 }
582
583 ao2_cleanup(session->cap);
584 ao2_cleanup(session->jointcap);
585 ao2_cleanup(session->peercap);
586
588}
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:457
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
Definition: rtp_engine.c:2196

References ao2_cleanup, ast_rtp_instance_destroy(), ast_rtp_instance_stop(), ast_string_field_free_memory, ast_xmpp_client_unref(), and session.

Referenced by jingle_alloc().

◆ jingle_session_hash()

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

Hashing function for Jingle sessions.

Definition at line 415 of file chan_motif.c.

416{
417 const struct jingle_session *session = obj;
418 const char *sid = obj;
419
420 return ast_str_hash(flags & OBJ_KEY ? sid : session->sid);
421}

References ast_str_hash(), OBJ_KEY, session, and jingle_session::sid.

Referenced by jingle_endpoint_state_create().

◆ jingle_session_lock_full()

static struct ast_channel * jingle_session_lock_full ( struct jingle_session pvt)
static

Definition at line 1148 of file chan_motif.c.

1149{
1150 struct ast_channel *chan;
1151
1152 /* Locking is simple when it is done right. If you see a deadlock resulting
1153 * in this function, it is not this function's fault, Your problem exists elsewhere.
1154 * This function is perfect... seriously. */
1155 for (;;) {
1156 /* First, get the channel and grab a reference to it */
1157 ao2_lock(pvt);
1158 chan = pvt->owner;
1159 if (chan) {
1160 /* The channel can not go away while we hold the pvt lock.
1161 * Give the channel a ref so it will not go away after we let
1162 * the pvt lock go. */
1163 ast_channel_ref(chan);
1164 } else {
1165 /* no channel, return pvt locked */
1166 return NULL;
1167 }
1168
1169 /* We had to hold the pvt lock while getting a ref to the owner channel
1170 * but now we have to let this lock go in order to preserve proper
1171 * locking order when grabbing the channel lock */
1172 ao2_unlock(pvt);
1173
1174 /* Look, no deadlock avoidance, hooray! */
1175 ast_channel_lock(chan);
1176 ao2_lock(pvt);
1177 if (pvt->owner == chan) {
1178 /* done */
1179 break;
1180 }
1181
1182 /* If the owner changed while everything was unlocked, no problem,
1183 * just start over and everthing will work. This is rare, do not be
1184 * confused by this loop and think this it is an expensive operation.
1185 * The majority of the calls to this function will never involve multiple
1186 * executions of this loop. */
1187 ast_channel_unlock(chan);
1188 ast_channel_unref(chan);
1189 ao2_unlock(pvt);
1190 }
1191
1192 /* If owner exists, it is locked and reffed */
1193 return pvt->owner;
1194}
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
struct ast_channel * owner
Definition: chan_motif.c:310

References ao2_lock, ao2_unlock, ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, NULL, and jingle_session::owner.

Referenced by jingle_action_session_accept(), jingle_action_session_info(), jingle_action_session_terminate(), jingle_interpret_content(), jingle_outgoing_hook(), and jingle_queue_hangup_with_cause().

◆ jingle_set_owner()

static void jingle_set_owner ( struct jingle_session session,
struct ast_channel chan 
)
static

Set the channel owner on the jingle_session object and related objects.

Definition at line 656 of file chan_motif.c.

657{
658 session->owner = chan;
659 if (session->rtp) {
661 }
662 if (session->vrtp) {
664 }
665}

References ast_channel_uniqueid(), ast_rtp_instance_set_channel_id(), and session.

Referenced by jingle_fixup(), jingle_hangup(), and jingle_new().

◆ jingle_set_rtp_peer()

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 
)
static

Function called by RTP engine to change where the remote party should send media.

Definition at line 642 of file chan_motif.c.

643{
644 return -1;
645}

◆ jingle_write()

static int jingle_write ( struct ast_channel ast,
struct ast_frame f 
)
static

Function called by core to write frames.

Definition at line 1698 of file chan_motif.c.

1699{
1701 int res = 0;
1702
1703 switch (frame->frametype) {
1704 case AST_FRAME_VOICE:
1706 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1707
1709 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1710 ast_format_get_name(frame->subclass.format),
1714 return 0;
1715 }
1716 if (session && session->rtp) {
1717 res = ast_rtp_instance_write(session->rtp, frame);
1718 }
1719 break;
1720 case AST_FRAME_VIDEO:
1721 if (session && session->vrtp) {
1722 res = ast_rtp_instance_write(session->vrtp, frame);
1723 }
1724 break;
1725 default:
1726 ast_log(LOG_WARNING, "Can't send %u type frames with Jingle write\n",
1727 frame->frametype);
1728 return 0;
1729 }
1730
1731 return res;
1732}
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
@ AST_FRAME_VIDEO
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:589
#define ast_str_alloca(init_len)
Definition: strings.h:848
Support for dynamic strings.
Definition: strings.h:623

References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_format_cap_get_names(), ast_format_cap_iscompatible_format(), AST_FORMAT_CAP_NAMES_LEN, AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log, ast_rtp_instance_write(), ast_str_alloca, ast_frame_subclass::format, ast_frame::frametype, LOG_WARNING, session, and ast_frame::subclass.

◆ load_module()

static int load_module ( void  )
static

Load the module.

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

Definition at line 2727 of file chan_motif.c.

2728{
2731 }
2732
2733 if (aco_info_init(&cfg_info)) {
2734 ast_log(LOG_ERROR, "Unable to intialize configuration for chan_motif.\n");
2735 goto end;
2736 }
2737
2738 aco_option_register(&cfg_info, "context", ACO_EXACT, endpoint_options, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, context));
2742 aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
2743 aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
2745 aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, cap));
2746 aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, cap));
2750 FLDSET(struct jingle_endpoint, maxicecandidates), DEFAULT_MAX_ICE_CANDIDATES);
2752 FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS);
2753
2755
2756 if (aco_process_config(&cfg_info, 0)) {
2757 ast_log(LOG_ERROR, "Unable to read config file motif.conf. Module loaded but not running.\n");
2758 aco_info_destroy(&cfg_info);
2762 }
2763
2764 if (!(sched = ast_sched_context_create())) {
2765 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2766 goto end;
2767 }
2768
2770 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2771 goto end;
2772 }
2773
2775
2777 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
2778 goto end;
2779 }
2780
2781 return 0;
2782
2783end:
2785
2786 if (sched) {
2788 }
2789
2790 aco_info_destroy(&cfg_info);
2792
2795
2797}
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
static char language[MAX_LANGUAGE]
Definition: chan_iax2.c:324
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:473
#define DEFAULT_MAX_PAYLOADS
Default maximum number of payloads we will offer.
Definition: chan_motif.c:223
static int custom_group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for groups.
Definition: chan_motif.c:2658
#define DEFAULT_MAX_ICE_CANDIDATES
Default maximum number of ICE candidates we will offer.
Definition: chan_motif.c:220
struct aco_type * endpoint_options[]
Definition: chan_motif.c:553
static int custom_transport_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for transport.
Definition: chan_motif.c:2699
static const char channel_type[]
Definition: chan_motif.c:321
static struct ast_rtp_glue jingle_rtp_glue
Local glue for interacting with the RTP engine core.
Definition: chan_motif.c:648
static int custom_connection_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for connection.
Definition: chan_motif.c:2674
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
@ ACO_EXACT
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_CODEC_T
Type for default option handler for format capabilities.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition: format_cap.c:216
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_rtp_glue_register(glue)
Definition: rtp_engine.h:893
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:407
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
struct ast_format_cap * capabilities
Definition: channel.h:632

References accountcode, ACO_EXACT, aco_info_destroy(), aco_info_init(), aco_option_register, aco_option_register_custom, aco_process_config(), ao2_cleanup, ao2_global_obj_release, ast_channel_register(), ast_format_cap_alloc, ast_format_cap_append_by_type(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MODULE_LOAD_DECLINE, ast_rtp_glue_register, ast_rtp_glue_unregister(), ast_sched_context_create(), ast_sched_context_destroy(), ast_sched_start_thread(), jingle_endpoint::cap, ast_channel_tech::capabilities, channel_type, voicemailpwcheck::context, custom_connection_handler(), custom_group_handler(), custom_transport_handler(), DEFAULT_MAX_ICE_CANDIDATES, DEFAULT_MAX_PAYLOADS, end, endpoint_options, FLDSET, globals, jingle_rtp_glue, jingle_tech, language, LOG_ERROR, jingle_endpoint::maxicecandidates, jingle_endpoint::maxpayloads, jingle_endpoint::musicclass, NULL, OPT_CODEC_T, OPT_STRINGFIELD_T, OPT_UINT_T, jingle_endpoint::parkinglot, PARSE_DEFAULT, and STRFLDSET.

◆ reload()

static int reload ( void  )
static

Reload module.

Definition at line 2800 of file chan_motif.c.

2801{
2802 if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
2803 return -1;
2804 }
2805
2806 return 0;
2807}
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.

References aco_process_config(), and ACO_PROCESS_ERROR.

◆ unload_module()

static int unload_module ( void  )
static

Unload the jingle channel from Asterisk.

Definition at line 2810 of file chan_motif.c.

2811{
2817 aco_info_destroy(&cfg_info);
2819
2820 return 0;
2821}
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570

References aco_info_destroy(), ao2_cleanup, ao2_global_obj_release, ast_channel_unregister(), ast_rtp_glue_unregister(), ast_sched_context_destroy(), ast_channel_tech::capabilities, globals, jingle_rtp_glue, jingle_tech, and NULL.

Variable Documentation

◆ __mod_info

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

Definition at line 2830 of file chan_motif.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2830 of file chan_motif.c.

◆ channel_type

const char channel_type[] = "Motif"
static

Definition at line 321 of file chan_motif.c.

Referenced by load_module().

◆ endpoint_option

struct aco_type endpoint_option
static

Definition at line 543 of file chan_motif.c.

◆ endpoint_options

struct aco_type* endpoint_options[] = ACO_TYPES(&endpoint_option)

Definition at line 553 of file chan_motif.c.

Referenced by load_module().

◆ jingle_action_handlers

const struct jingle_action_handler jingle_action_handlers[]
static

Referenced by jingle_action_hook().

◆ jingle_conf

struct aco_file jingle_conf
Initial value:
= {
.filename = "motif.conf",
}
static struct aco_type endpoint_option
Definition: chan_motif.c:543
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.

Definition at line 555 of file chan_motif.c.

◆ jingle_reason_mappings

const struct jingle_reason_mapping jingle_reason_mappings[]
static

◆ jingle_rtp_glue

struct ast_rtp_glue jingle_rtp_glue
static

Local glue for interacting with the RTP engine core.

Definition at line 648 of file chan_motif.c.

Referenced by load_module(), and unload_module().

◆ jingle_tech

struct ast_channel_tech jingle_tech
static

PBX interface structure for channel registration.

Definition at line 353 of file chan_motif.c.

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

◆ sched

struct ast_sched_context* sched
static

Scheduling context for RTCP

Definition at line 329 of file chan_motif.c.