Asterisk - The Open Source Telephony Project GIT-master-7805f28
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 session 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-initiate 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 262 of file chan_motif.c.

◆ DEFAULT_MAX_PAYLOADS

#define DEFAULT_MAX_PAYLOADS   "30"

Default maximum number of payloads we will offer.

Definition at line 265 of file chan_motif.c.

◆ ENDPOINT_BUCKETS

#define ENDPOINT_BUCKETS   37

Number of buckets for endpoints.

Definition at line 268 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 295 of file chan_motif.c.

◆ GOOGLE_SESSION_NS

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

Namespace for Google Session.

Definition at line 292 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 286 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 289 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 298 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 283 of file chan_motif.c.

◆ JINGLE_NS

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

Namespace for Jingle itself.

Definition at line 274 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 280 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 277 of file chan_motif.c.

◆ SESSION_BUCKETS

#define SESSION_BUCKETS   37

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

Definition at line 271 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 301 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 304 of file chan_motif.c.

304 {
305 JINGLE_TRANSPORT_ICE_UDP = 3, /*!< XEP-0176 */
306 JINGLE_TRANSPORT_GOOGLE_V2 = 2, /*!< https://developers.google.com/talk/call_signaling */
307 JINGLE_TRANSPORT_GOOGLE_V1 = 1, /*!< Undocumented initial Google specification */
308 JINGLE_TRANSPORT_NONE = 0, /*!< No transport specified */
309};
@ JINGLE_TRANSPORT_ICE_UDP
Definition: chan_motif.c:305
@ JINGLE_TRANSPORT_GOOGLE_V1
Definition: chan_motif.c:307
@ JINGLE_TRANSPORT_NONE
Definition: chan_motif.c:308
@ JINGLE_TRANSPORT_GOOGLE_V2
Definition: chan_motif.c:306

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2872 of file chan_motif.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2872 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 2872 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 2716 of file chan_motif.c.

2717{
2718 struct jingle_endpoint *endpoint = obj;
2719
2720 /* You might think... but Josh, shouldn't you do this in a prelink callback? Well I *could* but until the original is destroyed
2721 * this will not actually get called, so even if the config turns out to be bogus this is harmless.
2722 */
2723 if (!(endpoint->connection = ast_xmpp_client_find(var->value))) {
2724 ast_log(LOG_ERROR, "Connection '%s' configured on endpoint '%s' could not be found\n", var->value, endpoint->name);
2725 return -1;
2726 }
2727
2728 if (!(endpoint->rule = iks_filter_add_rule(endpoint->connection->filter, jingle_action_hook, endpoint,
2729 IKS_RULE_TYPE, IKS_PAK_IQ,
2730 IKS_RULE_NS, JINGLE_NS,
2731 IKS_RULE_NS, GOOGLE_SESSION_NS,
2732 IKS_RULE_DONE))) {
2733 ast_log(LOG_ERROR, "Action hook could not be added to connection '%s' on endpoint '%s'\n", var->value, endpoint->name);
2734 return -1;
2735 }
2736
2737 return 0;
2738}
#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:2637
#define GOOGLE_SESSION_NS
Namespace for Google Session.
Definition: chan_motif.c:292
#define JINGLE_NS
Namespace for Jingle itself.
Definition: chan_motif.c:274
#define LOG_ERROR
iksfilter * filter
Definition: xmpp.h:128
Endpoint which contains configuration information and active sessions.
Definition: chan_motif.c:317
iksrule * rule
Definition: chan_motif.c:327
struct ast_xmpp_client * connection
Definition: chan_motif.c:326
const ast_string_field name
Definition: chan_motif.c:325
struct ast_xmpp_client * ast_xmpp_client_find(const char *name)
Find an XMPP client connection using a given name.
Definition: res_xmpp.c:1010

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

2701{
2702 struct jingle_endpoint *endpoint = obj;
2703
2704 if (!strcasecmp(var->name, "callgroup")) {
2705 endpoint->callgroup = ast_get_group(var->value);
2706 } else if (!strcasecmp(var->name, "pickupgroup")) {
2707 endpoint->pickupgroup = ast_get_group(var->value);
2708 } else {
2709 return -1;
2710 }
2711
2712 return 0;
2713}
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7591
ast_group_t pickupgroup
Definition: chan_motif.c:332
ast_group_t callgroup
Definition: chan_motif.c:331

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

2742{
2743 struct jingle_endpoint *endpoint = obj;
2744
2745 if (!strcasecmp(var->value, "ice-udp")) {
2747 } else if (!strcasecmp(var->value, "google")) {
2749 } else if (!strcasecmp(var->value, "google-v1")) {
2751 } else {
2752 ast_log(LOG_WARNING, "Unknown transport type '%s' on endpoint '%s', defaulting to 'ice-udp'\n", var->value, endpoint->name);
2754 }
2755
2756 return 0;
2757}
#define LOG_WARNING
enum jingle_transport transport
Definition: chan_motif.c:333

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

2638{
2639 char *action;
2640 const char *sid = NULL;
2641 struct jingle_session *session = NULL;
2642 struct jingle_endpoint *endpoint = data;
2643 int i, handled = 0;
2644
2645 /* We accept both Jingle and Google-V1 */
2646 if (!(action = iks_find_attrib(pak->query, "action")) &&
2647 !(action = iks_find_attrib(pak->query, "type"))) {
2648 /* This occurs if either receive a packet masquerading as Jingle or Google-V1 that is actually not OR we receive a response
2649 * to a message that has no response hook. */
2650 return IKS_FILTER_EAT;
2651 }
2652
2653 /* Bump the endpoint reference count up in case a reload occurs. Unfortunately the available synchronization between iksemel and us
2654 * does not permit us to make this completely safe. */
2655 ao2_ref(endpoint, +1);
2656
2657 /* If a Jingle session identifier is present use it */
2658 if (!(sid = iks_find_attrib(pak->query, "sid"))) {
2659 /* If a Google-V1 session identifier is present use it */
2660 sid = iks_find_attrib(pak->query, "id");
2661 }
2662
2663 /* If a session identifier was present in the message attempt to find the session, it is up to the action handler whether
2664 * this is required or not */
2665 if (!ast_strlen_zero(sid)) {
2666 session = ao2_find(endpoint->state->sessions, sid, OBJ_KEY);
2667 }
2668
2669 /* If a session is present associate the callid with this thread */
2670 if (session) {
2672 }
2673
2674 /* Iterate through supported action handlers looking for one that is able to handle this */
2675 for (i = 0; i < ARRAY_LEN(jingle_action_handlers); i++) {
2676 if (!strcasecmp(jingle_action_handlers[i].action, action)) {
2677 jingle_action_handlers[i].handler(endpoint, session, pak);
2678 handled = 1;
2679 break;
2680 }
2681 }
2682
2683 /* If no action handler is present for the action they sent us make it evident */
2684 if (!handled) {
2685 ast_log(LOG_NOTICE, "Received action '%s' for session '%s' that has no handler\n", action, sid);
2686 }
2687
2688 /* If a session was successfully found for this message deref it now since the handler is done */
2689 if (session) {
2691 ao2_ref(session, -1);
2692 }
2693
2694 ao2_ref(endpoint, -1);
2695
2696 return IKS_FILTER_EAT;
2697}
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:2295
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:2314
#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:417
struct ao2_container * sessions
Definition: chan_motif.c:313
struct jingle_endpoint_state * state
Definition: chan_motif.c:334
Session which contains information about an active session.
Definition: chan_motif.c:338
#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 2516 of file chan_motif.c.

2517{
2518 struct ast_channel *chan;
2519
2520 if (!session) {
2521 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2522 "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2523 return;
2524 }
2525
2526
2528
2529 if ((chan = jingle_session_lock_full(session))) {
2531 ast_channel_unlock(chan);
2532 ast_channel_unref(chan);
2533 }
2535
2536 jingle_send_response(endpoint->connection, pak);
2537}
#define ao2_unlock(a)
Definition: astobj2.h:729
static struct ast_channel * jingle_session_lock_full(struct jingle_session *pvt)
Definition: chan_motif.c:1190
static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
Helper function which locates content stanzas and interprets them.
Definition: chan_motif.c:2321
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:926
static void jingle_send_response(struct ast_xmpp_client *connection, ikspak *pak)
Internal helper function which sends a response.
Definition: chan_motif.c:906
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1269
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
#define ast_channel_unlock(chan)
Definition: channel.h:2973
@ 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 2540 of file chan_motif.c.

2541{
2542 struct ast_channel *chan;
2543
2544 if (!session) {
2545 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2546 "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2547 return;
2548 }
2549
2550 if (!(chan = jingle_session_lock_full(session))) {
2552 jingle_send_response(endpoint->connection, pak);
2553 return;
2554 }
2555
2556 if (iks_find_with_attrib(pak->query, "ringing", "xmlns", JINGLE_RTP_INFO_NS)) {
2558 if (ast_channel_state(chan) != AST_STATE_UP) {
2560 }
2561 } else if (iks_find_with_attrib(pak->query, "hold", "xmlns", JINGLE_RTP_INFO_NS)) {
2562 ast_queue_hold(chan, NULL);
2563 } else if (iks_find_with_attrib(pak->query, "unhold", "xmlns", JINGLE_RTP_INFO_NS)) {
2564 ast_queue_unhold(chan);
2565 }
2566
2567 ast_channel_unlock(chan);
2568 ast_channel_unref(chan);
2570
2571 jingle_send_response(endpoint->connection, pak);
2572}
#define JINGLE_RTP_INFO_NS
Namespace for Jingle RTP info.
Definition: chan_motif.c:280
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1254
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1229
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:7359
@ 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 2432 of file chan_motif.c.

2433{
2434 char *sid;
2435 enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
2436 struct ast_channel *chan;
2437 int res;
2438
2439 if (session) {
2440 /* This is a duplicate session setup, so respond accordingly */
2441 jingle_send_error_response(endpoint->connection, pak, "result", "out-of-order", NULL);
2442 return;
2443 }
2444
2445 /* Retrieve the session identifier from the message, note that this may alter the transport */
2446 if ((sid = iks_find_attrib(pak->query, "id"))) {
2447 /* The presence of the session identifier in the 'id' attribute tells us that this is Google-V1 as everything else uses 'sid' */
2448 transport = JINGLE_TRANSPORT_GOOGLE_V1;
2449 } else if (!(sid = iks_find_attrib(pak->query, "sid"))) {
2450 jingle_send_error_response(endpoint->connection, pak, "bad-request", NULL, NULL);
2451 return;
2452 }
2453
2454 /* Create a new local session */
2455 if (!(session = jingle_alloc(endpoint, pak->from->full, sid))) {
2456 jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2457 return;
2458 }
2459
2460 /* If we determined that the transport should change as a result of how we got the SID change it */
2461 if (transport != JINGLE_TRANSPORT_NONE) {
2462 session->transport = transport;
2463 }
2464
2465 /* Create a new Asterisk channel using the above local session */
2466 if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, pak->from->user, NULL, NULL, pak->from->full))) {
2467 ao2_ref(session, -1);
2468 jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2469 return;
2470 }
2471
2472 ao2_link(endpoint->state->sessions, session);
2473
2474 ast_channel_lock(chan);
2476 ast_channel_unlock(chan);
2477 res = ast_pbx_start(chan);
2478
2479 switch (res) {
2480 case AST_PBX_FAILED:
2481 ast_log(LOG_WARNING, "Failed to start PBX :(\n");
2482 jingle_send_error_response(endpoint->connection, pak, "cancel", "service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2483 session->gone = 1;
2484 ast_hangup(chan);
2485 break;
2486 case AST_PBX_CALL_LIMIT:
2487 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
2488 jingle_send_error_response(endpoint->connection, pak, "wait", "resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", NULL);
2489 ast_hangup(chan);
2490 break;
2491 case AST_PBX_SUCCESS:
2492 jingle_send_response(endpoint->connection, pak);
2493
2494 /* Only send a transport-info message if we successfully interpreted the available content */
2495 if (!jingle_interpret_content(session, pak)) {
2496 jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
2497 }
2498 break;
2499 }
2500}
#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:810
jingle_transport
The various transport methods supported, from highest priority to lowest priority when doing fallback...
Definition: chan_motif.c:304
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:743
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:1253
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2510
#define ast_channel_lock(chan)
Definition: channel.h:2972
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_PBX_FAILED
Definition: pbx.h:373
@ AST_PBX_CALL_LIMIT
Definition: pbx.h:374
@ AST_PBX_SUCCESS
Definition: pbx.h:372
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4723

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

2576{
2577 struct ast_channel *chan;
2578 iks *reason, *text;
2579 int cause = AST_CAUSE_NORMAL;
2580 struct ast_control_pvt_cause_code *cause_code;
2581 int data_size = sizeof(*cause_code);
2582
2583 if (!session) {
2584 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2585 "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2586 return;
2587 }
2588
2589 if (!(chan = jingle_session_lock_full(session))) {
2591 jingle_send_response(endpoint->connection, pak);
2592 return;
2593 }
2594
2595 /* Pull the reason text from the session-terminate message and translate it into a cause code */
2596 if ((reason = iks_find(pak->query, "reason")) && (text = iks_child(reason))) {
2597 int i;
2598
2599 /* Size of the string making up the cause code is "Motif " + text */
2600 data_size += 6 + strlen(iks_name(text));
2601 cause_code = ast_alloca(data_size);
2602 memset(cause_code, 0, data_size);
2603
2604 /* Get the appropriate cause code mapping for this reason */
2605 for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
2606 if (!strcasecmp(jingle_reason_mappings[i].reason, iks_name(text))) {
2607 cause = jingle_reason_mappings[i].cause;
2608 break;
2609 }
2610 }
2611
2612 /* Store the technology specific information */
2613 snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "Motif %s", iks_name(text));
2614 } else {
2615 /* No technology specific information is available */
2616 cause_code = ast_alloca(data_size);
2617 memset(cause_code, 0, data_size);
2618 }
2619
2621 cause_code->ast_cause = cause;
2622 ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
2623 ast_channel_hangupcause_hash_set(chan, cause_code, data_size);
2624
2625 ast_debug(3, "Hanging up channel '%s' due to session terminate message with cause '%d'\n", ast_channel_name(chan), cause);
2626 ast_queue_hangup_with_cause(chan, cause);
2627 session->gone = 1;
2628
2629 ast_channel_unlock(chan);
2630 ast_channel_unref(chan);
2632
2633 jingle_send_response(endpoint->connection, pak);
2634}
char * text
Definition: app_queue.c:1809
#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:1276
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1204
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:4304
#define AST_CHANNEL_NAME
Definition: channel.h:173
@ 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 2503 of file chan_motif.c.

2504{
2505 if (!session) {
2506 jingle_send_error_response(endpoint->connection, pak, "cancel", "item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
2507 "unknown-session xmlns='urn:xmpp:jingle:errors:1'");
2508 return;
2509 }
2510
2512 jingle_send_response(endpoint->connection, pak);
2513}

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

1436{
1437 int res = 0;
1438
1439 if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
1440 iks_insert_attrib(content, "creator", session->outgoing ? "initiator" : "responder");
1441 iks_insert_attrib(content, "name", name);
1442 iks_insert_node(jingle, content);
1443
1444 iks_insert_attrib(description, "xmlns", JINGLE_RTP_NS);
1445 if (type == AST_MEDIA_TYPE_AUDIO) {
1446 iks_insert_attrib(description, "media", "audio");
1447 } else if (type == AST_MEDIA_TYPE_VIDEO) {
1448 iks_insert_attrib(description, "media", "video");
1449 } else {
1450 return -1;
1451 }
1452 iks_insert_node(content, description);
1453 } else {
1454 iks_insert_attrib(description, "xmlns", GOOGLE_PHONE_NS);
1455 iks_insert_node(jingle, description);
1456 }
1457
1458 if (!(res = jingle_add_payloads_to_description(session, rtp, description, payloads, type))) {
1459 if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1460 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
1461 iks_insert_node(content, transport);
1462 } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1463 iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
1464 iks_insert_node(content, transport);
1465 }
1466 }
1467
1468 return res;
1469}
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:1348
#define GOOGLE_PHONE_NS
Namespace for Google Phone description.
Definition: chan_motif.c:295
#define JINGLE_RTP_NS
Namespace for Jingle RTP sessions.
Definition: chan_motif.c:277
#define GOOGLE_TRANSPORT_NS
Namespace for Google Talk ICE-UDP.
Definition: chan_motif.c:286
#define JINGLE_ICE_UDP_NS
Namespace for Jingle ICE-UDP.
Definition: chan_motif.c:283
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 1022 of file chan_motif.c.

1023{
1024 struct ast_rtp_engine_ice *ice;
1025 struct ao2_container *local_candidates;
1026 struct ao2_iterator it;
1027 struct ast_rtp_engine_ice_candidate *candidate;
1028 int i = 0, res = 0;
1029
1030 if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
1031 ast_log(LOG_ERROR, "Unable to add Google ICE candidates as ICE support not available or no candidates available\n");
1032 return -1;
1033 }
1034
1035 if (transport_type != JINGLE_TRANSPORT_GOOGLE_V1) {
1036 iks_insert_attrib(transport, "xmlns", GOOGLE_TRANSPORT_NS);
1037 }
1038
1039 it = ao2_iterator_init(local_candidates, 0);
1040
1041 while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
1042 iks *local_candidate;
1043 /* In Google land a username is 16 bytes, explicitly */
1044 char ufrag[17] = "";
1045
1046 if (!(local_candidate = iks_new("candidate"))) {
1047 res = -1;
1048 ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for Google ICE transport\n");
1049 break;
1050 }
1051
1052 if (candidate->id == 1) {
1053 iks_insert_attrib(local_candidate, "name", !video ? "rtp" : "video_rtp");
1054 } else if (candidate->id == 2) {
1055 iks_insert_attrib(local_candidate, "name", !video ? "rtcp" : "video_rtcp");
1056 } else {
1057 iks_delete(local_candidate);
1058 continue;
1059 }
1060
1061 iks_insert_attrib(local_candidate, "address", ast_sockaddr_stringify_host(&candidate->address));
1062 iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
1063
1064 if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
1065 iks_insert_attrib(local_candidate, "preference", "0.95");
1066 iks_insert_attrib(local_candidate, "type", "local");
1067 } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
1068 iks_insert_attrib(local_candidate, "preference", "0.9");
1069 iks_insert_attrib(local_candidate, "type", "stun");
1070 }
1071
1072 iks_insert_attrib(local_candidate, "protocol", "udp");
1073 iks_insert_attrib(local_candidate, "network", "0");
1074 snprintf(ufrag, sizeof(ufrag), "%s", ice->get_ufrag(rtp));
1075 iks_insert_attrib(local_candidate, "username", ufrag);
1076 iks_insert_attrib(local_candidate, "generation", "0");
1077
1078 if (transport_type == JINGLE_TRANSPORT_GOOGLE_V1) {
1079 iks_insert_attrib(local_candidate, "password", "");
1080 iks_insert_attrib(local_candidate, "foundation", "0");
1081 iks_insert_attrib(local_candidate, "component", "1");
1082 } else {
1083 iks_insert_attrib(local_candidate, "password", ice->get_password(rtp));
1084 }
1085
1086 /* You may notice a lack of relay support up above - this is because we don't support it for use with
1087 * the Google talk transport due to their arcane support. */
1088
1089 iks_insert_node(transport, local_candidate);
1090 candidates[i++] = local_candidate;
1091 }
1092
1094 ao2_ref(local_candidates, -1);
1095
1096 return res;
1097}
#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:508
@ AST_RTP_ICE_CANDIDATE_TYPE_HOST
Definition: rtp_engine.h:507
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:3097
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:525
struct ast_sockaddr address
Definition: rtp_engine.h:530
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:527
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:532
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:536
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:546
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:548
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:550

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

961{
962 struct ast_rtp_engine_ice *ice;
963 struct ao2_container *local_candidates;
964 struct ao2_iterator it;
965 struct ast_rtp_engine_ice_candidate *candidate;
966 int i = 0, res = 0;
967
968 if (!(ice = ast_rtp_instance_get_ice(rtp)) || !(local_candidates = ice->get_local_candidates(rtp))) {
969 ast_log(LOG_ERROR, "Unable to add ICE-UDP candidates as ICE support not available or no candidates available\n");
970 return -1;
971 }
972
973 iks_insert_attrib(transport, "xmlns", JINGLE_ICE_UDP_NS);
974 iks_insert_attrib(transport, "pwd", ice->get_password(rtp));
975 iks_insert_attrib(transport, "ufrag", ice->get_ufrag(rtp));
976
977 it = ao2_iterator_init(local_candidates, 0);
978
979 while ((candidate = ao2_iterator_next(&it)) && (i < maximum)) {
980 iks *local_candidate;
981 char tmp[30];
982
983 if (!(local_candidate = iks_new("candidate"))) {
984 res = -1;
985 ast_log(LOG_ERROR, "Unable to allocate IKS candidate stanza for ICE-UDP transport\n");
986 break;
987 }
988
989 snprintf(tmp, sizeof(tmp), "%u", candidate->id);
990 iks_insert_attrib(local_candidate, "component", tmp);
991 snprintf(tmp, sizeof(tmp), "%d", ast_str_hash(candidate->foundation));
992 iks_insert_attrib(local_candidate, "foundation", tmp);
993 iks_insert_attrib(local_candidate, "generation", "0");
994 iks_insert_attrib(local_candidate, "network", "0");
995 snprintf(tmp, sizeof(tmp), "%04lx", (unsigned long)(ast_random() & 0xffff));
996 iks_insert_attrib(local_candidate, "id", tmp);
997 iks_insert_attrib(local_candidate, "ip", ast_sockaddr_stringify_host(&candidate->address));
998 iks_insert_attrib(local_candidate, "port", ast_sockaddr_stringify_port(&candidate->address));
999 snprintf(tmp, sizeof(tmp), "%d", candidate->priority);
1000 iks_insert_attrib(local_candidate, "priority", tmp);
1001 iks_insert_attrib(local_candidate, "protocol", "udp");
1002
1003 if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_HOST) {
1004 iks_insert_attrib(local_candidate, "type", "host");
1005 } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_SRFLX) {
1006 iks_insert_attrib(local_candidate, "type", "srflx");
1007 } else if (candidate->type == AST_RTP_ICE_CANDIDATE_TYPE_RELAYED) {
1008 iks_insert_attrib(local_candidate, "type", "relay");
1009 }
1010
1011 iks_insert_node(transport, local_candidate);
1012 candidates[i++] = local_candidate;
1013 }
1014
1016 ao2_ref(local_candidates, -1);
1017
1018 return res;
1019}
@ AST_RTP_ICE_CANDIDATE_TYPE_RELAYED
Definition: rtp_engine.h:509
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, 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 1348 of file chan_motif.c.

1349{
1350 int x = 0, i = 0, res = 0;
1351
1352 for (x = 0; (x < ast_format_cap_count(session->jointcap)) && (i < (session->maxpayloads - 2)); x++) {
1353 struct ast_format *format = ast_format_cap_get_format(session->jointcap, x);
1354 int rtp_code;
1355 iks *payload;
1356 char tmp[32];
1357
1358 if (ast_format_get_type(format) != type) {
1359 ao2_ref(format, -1);
1360 continue;
1361 }
1362
1363 if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(rtp), 1, format, 0)) == -1) ||
1364 (!(payload = iks_new("payload-type")))) {
1365 ao2_ref(format, -1);
1366 return -1;
1367 }
1368
1369 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1370 iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
1371 }
1372
1373 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
1374 iks_insert_attrib(payload, "id", tmp);
1375 iks_insert_attrib(payload, "name", ast_rtp_lookup_mime_subtype2(1, format, 0, 0));
1376 iks_insert_attrib(payload, "channels", "1");
1377
1379 ((session->transport == JINGLE_TRANSPORT_GOOGLE_V1) || (session->transport == JINGLE_TRANSPORT_GOOGLE_V2))) {
1380 iks_insert_attrib(payload, "clockrate", "16000");
1381 } else {
1382 snprintf(tmp, sizeof(tmp), "%u", ast_rtp_lookup_sample_rate2(1, format, 0));
1383 iks_insert_attrib(payload, "clockrate", tmp);
1384 }
1385
1386 if ((type == AST_MEDIA_TYPE_VIDEO) && (session->transport == JINGLE_TRANSPORT_GOOGLE_V2)) {
1387 iks *parameter;
1388
1389 /* Google requires these parameters to be set, but alas we can not give accurate values so use some safe defaults */
1390 if ((parameter = iks_new("parameter"))) {
1391 iks_insert_attrib(parameter, "name", "width");
1392 iks_insert_attrib(parameter, "value", "640");
1393 iks_insert_node(payload, parameter);
1394 }
1395 if ((parameter = iks_new("parameter"))) {
1396 iks_insert_attrib(parameter, "name", "height");
1397 iks_insert_attrib(parameter, "value", "480");
1398 iks_insert_node(payload, parameter);
1399 }
1400 if ((parameter = iks_new("parameter"))) {
1401 iks_insert_attrib(parameter, "name", "framerate");
1402 iks_insert_attrib(parameter, "value", "30");
1403 iks_insert_node(payload, parameter);
1404 }
1405 }
1406
1407 iks_insert_node(description, payload);
1408 payloads[i++] = payload;
1409
1410 ao2_ref(format, -1);
1411 }
1412 /* If this is for audio and there is room for RFC2833 add it in */
1413 if ((type == AST_MEDIA_TYPE_AUDIO) && (i < session->maxpayloads)) {
1414 iks *payload;
1415
1416 if ((payload = iks_new("payload-type"))) {
1417 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1418 iks_insert_attrib(payload, "xmlns", GOOGLE_PHONE_NS);
1419 }
1420
1421 iks_insert_attrib(payload, "id", "101");
1422 iks_insert_attrib(payload, "name", "telephone-event");
1423 iks_insert_attrib(payload, "channels", "1");
1424 iks_insert_attrib(payload, "clockrate", "8000");
1425 iks_insert_node(description, payload);
1426 payloads[i++] = payload;
1427 }
1428 }
1429
1430 return res;
1431}
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:2204
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:2174
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:755
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:2025
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, 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 743 of file chan_motif.c.

744{
745 struct jingle_session *session;
747 struct ast_sockaddr tmp;
748
750 return NULL;
751 }
752
754 session->callid = (callid ? callid : ast_create_callid());
755
756 if (ast_string_field_init(session, 512)) {
757 ao2_ref(session, -1);
758 return NULL;
759 }
760
761 if (!ast_strlen_zero(from)) {
762 ast_copy_string(session->remote_original, from, sizeof(session->remote_original));
763 ast_copy_string(session->remote, from, sizeof(session->remote));
764 }
765
766 if (ast_strlen_zero(sid)) {
767 ast_string_field_build(session, sid, "%08lx%08lx", (unsigned long)ast_random(), (unsigned long)ast_random());
768 session->outgoing = 1;
769 ast_string_field_set(session, audio_name, "audio");
770 ast_string_field_set(session, video_name, "video");
771 } else {
772 ast_string_field_set(session, sid, sid);
773 }
774
775 ao2_ref(endpoint->state, +1);
776 session->state = endpoint->state;
777 ao2_ref(endpoint->connection, +1);
778 session->connection = endpoint->connection;
779 session->transport = endpoint->transport;
780
784 !session->callid) {
785 ao2_ref(session, -1);
786 return NULL;
787 }
788
790
791 /* While we rely on res_xmpp for communication we still need a temporary ast_sockaddr to tell the RTP engine
792 * that we want IPv4 */
793 ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
794
795 /* Sessions always carry audio, but video is optional so don't enable it here */
796 if (!(session->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
797 ao2_ref(session, -1);
798 return NULL;
799 }
802
803 session->maxicecandidates = endpoint->maxicecandidates;
804 session->maxpayloads = endpoint->maxpayloads;
805
806 return session;
807}
#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:603
@ 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:2273
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:2268
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:493
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:733
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:126
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:120
#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:329
unsigned int maxicecandidates
Definition: chan_motif.c:328
struct ast_format_cap * cap
Definition: chan_motif.c:330
ast_callid callid
Definition: chan_motif.c:360
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, 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 1667 of file chan_motif.c.

1668{
1670
1671 /* The channel has already been answered so we don't need to do anything */
1672 if (ast_channel_state(ast) == AST_STATE_UP) {
1673 return 0;
1674 }
1675
1677
1678 return 0;
1679}
static void jingle_send_session_accept(struct jingle_session *session)
Internal function which sends a session-accept message.
Definition: chan_motif.c:1560
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 1892 of file chan_motif.c.

1893{
1895
1897
1898 /* Since we have no idea of the remote capabilities use ours for now */
1900
1901 /* We set up a hook so we can know when our session-initiate message was accepted or rejected */
1902 session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1903 IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1904
1906
1907 return 0;
1908}
static void jingle_send_session_initiate(struct jingle_session *session)
Internal function which sends a session-initiate message.
Definition: chan_motif.c:1554
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:1566

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

641{
642 struct jingle_config *cfg;
643
644 if (!(cfg = ao2_alloc(sizeof(*cfg), jingle_config_destructor))) {
645 return NULL;
646 }
647
650 if (!cfg->endpoints) {
651 ao2_ref(cfg, -1);
652 return NULL;
653 }
654
655 return cfg;
656}
@ 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:633
static int jingle_endpoint_cmp(void *obj, void *arg, int flags)
Comparator function for Jingle endpoints.
Definition: chan_motif.c:577
#define ENDPOINT_BUCKETS
Number of buckets for endpoints.
Definition: chan_motif.c:268
static int jingle_endpoint_hash(const void *obj, const int flags)
Hashing function for Jingle endpoints.
Definition: chan_motif.c:568
struct ao2_container * endpoints
Definition: chan_motif.c:366

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

634{
635 struct jingle_config *cfg = obj;
637}
#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 1868 of file chan_motif.c.

1869{
1871
1872 if (session->rtp) {
1874 }
1875
1876 return 0;
1877}
char digit
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
Definition: rtp_engine.c:2263

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

1881{
1883
1884 if (session->rtp) {
1886 }
1887
1888 return 0;
1889}
int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
Definition: rtp_engine.c:2291

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 session if possible.

Definition at line 710 of file chan_motif.c.

711{
712 struct ast_sockaddr tmp;
713 struct ast_rtp_engine_ice *ice;
714
715 /* If video is already present don't do anything */
716 if (session->vrtp) {
717 return;
718 }
719
720 /* If there are no configured video codecs do not turn video support on, it just won't work */
722 return;
723 }
724
725 ast_sockaddr_parse(&tmp, "0.0.0.0", 0);
726
727 if (!(session->vrtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
728 return;
729 }
730
737 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2 && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
738 ice->stop(session->vrtp);
739 }
740}
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:2395
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:1677
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:581
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:2374
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:544

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

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

542{
543 struct jingle_endpoint *endpoint;
544
545 if (!(endpoint = ao2_alloc(sizeof(*endpoint), jingle_endpoint_destructor))) {
546 return NULL;
547 }
548
549 if (ast_string_field_init(endpoint, 512)) {
550 ao2_ref(endpoint, -1);
551 return NULL;
552 }
553
554 if (!(endpoint->state = jingle_endpoint_state_find_or_create(cat))) {
555 ao2_ref(endpoint, -1);
556 return NULL;
557 }
558
559 ast_string_field_set(endpoint, name, cat);
560
563
564 return endpoint;
565}
static void jingle_endpoint_destructor(void *obj)
Destructor for Jingle endpoints.
Definition: chan_motif.c:483
static struct jingle_endpoint_state * jingle_endpoint_state_find_or_create(const char *category)
State find/create function.
Definition: chan_motif.c:527

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

578{
579 struct jingle_endpoint *endpoint1 = obj, *endpoint2 = arg;
580 const char *name = arg;
581
582 return !strcmp(endpoint1->name, flags & OBJ_KEY ? name : endpoint2->name) ? CMP_MATCH | CMP_STOP : 0;
583}
@ 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 483 of file chan_motif.c.

484{
485 struct jingle_endpoint *endpoint = obj;
486
487 if (endpoint->rule) {
488 iks_filter_remove_rule(endpoint->connection->filter, endpoint->rule);
489 }
490
491 if (endpoint->connection) {
493 }
494
495 ao2_cleanup(endpoint->cap);
496 ao2_ref(endpoint->state, -1);
497
499}
#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:1023

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

503{
504 return ao2_find(tmp_container, category, OBJ_KEY);
505}

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

569{
570 const struct jingle_endpoint *endpoint = obj;
571 const char *name = obj;
572
573 return ast_str_hash(flags & OBJ_KEY ? name : endpoint->name);
574}

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

509{
511
513 return NULL;
514 }
515
518 if (!state->sessions) {
519 ao2_ref(state, -1);
520 return NULL;
521 }
522
523 return state;
524}
enum cc_state state
Definition: ccss.c:399
#define SESSION_BUCKETS
Number of buckets for sessions, on a per-endpoint basis.
Definition: chan_motif.c:271
static void jingle_endpoint_state_destructor(void *obj)
Destructor for Jingle endpoint state.
Definition: chan_motif.c:475
static int jingle_session_hash(const void *obj, const int flags)
Hashing function for Jingle sessions.
Definition: chan_motif.c:457
static int jingle_session_cmp(void *obj, void *arg, int flags)
Comparator function for Jingle sessions.
Definition: chan_motif.c:466
Endpoint state information.
Definition: chan_motif.c:312

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

476{
477 struct jingle_endpoint_state *state = obj;
478
479 ao2_ref(state->sessions, -1);
480}

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

528{
530 RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
531
532 if (!cfg || !cfg->endpoints || !(endpoint = jingle_endpoint_find(cfg->endpoints, category))) {
534 }
535
536 ao2_ref(endpoint->state, +1);
537 return endpoint->state;
538}
#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:502
static struct jingle_endpoint_state * jingle_endpoint_state_create(void)
Allocator function for Jingle endpoint state.
Definition: chan_motif.c:508
#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 1777 of file chan_motif.c.

1778{
1779 struct jingle_session *session = ast_channel_tech_pvt(newchan);
1780
1782
1783 jingle_set_owner(session, newchan);
1784
1786
1787 return 0;
1788}
#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:698

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

680{
681}

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

664{
667
668 if (!session->rtp) {
670 }
671
672 ao2_ref(session->rtp, +1);
673 *instance = session->rtp;
674
675 return res;
676}
ast_rtp_glue_result
Definition: rtp_engine.h:161
@ AST_RTP_GLUE_RESULT_LOCAL
Definition: rtp_engine.h:167
@ AST_RTP_GLUE_RESULT_FORBID
Definition: rtp_engine.h:163

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

1912{
1914
1916
1917 if ((ast_channel_state(ast) != AST_STATE_DOWN) && !session->gone) {
1918 int cause = (session->owner ? ast_channel_hangupcause(session->owner) : AST_CAUSE_CONGESTION);
1919 const char *reason = "success";
1920 int i;
1921
1922 /* Get the appropriate reason and send a session-terminate */
1923 for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
1924 if (jingle_reason_mappings[i].cause == cause) {
1925 reason = jingle_reason_mappings[i].reason;
1926 break;
1927 }
1928 }
1929
1931 }
1932
1935
1936 ao2_unlink(session->state->sessions, session);
1937 ao2_ref(session->state, -1);
1938
1940 ao2_ref(session, -1);
1941
1942 return 0;
1943}
#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:1100
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:435

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

1792{
1794 int res = 0;
1795
1796 switch (condition) {
1798 if (ast_channel_state(ast) == AST_STATE_RING) {
1799 jingle_send_session_info(session, "ringing xmlns='urn:xmpp:jingle:apps:rtp:info:1'");
1800 } else {
1801 res = -1;
1802 }
1803 break;
1804 case AST_CONTROL_BUSY:
1805 if (ast_channel_state(ast) != AST_STATE_UP) {
1808 } else {
1809 res = -1;
1810 }
1811 break;
1813 if (ast_channel_state(ast) != AST_STATE_UP) {
1816 } else {
1817 res = -1;
1818 }
1819 break;
1821 if (ast_channel_state(ast) != AST_STATE_UP) {
1824 }
1825 break;
1826 case AST_CONTROL_HOLD:
1827 ast_moh_start(ast, data, NULL);
1828 break;
1829 case AST_CONTROL_UNHOLD:
1830 ast_moh_stop(ast);
1831 break;
1833 if (session->rtp) {
1835 }
1836 break;
1838 if (session->rtp) {
1840 }
1841 break;
1845 break;
1848 case -1:
1849 res = -1;
1850 break;
1851 default:
1852 ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);
1853 res = -1;
1854 }
1855
1856 return res;
1857}
#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:1140
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2427
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
@ 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:7739
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7749
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:2342
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:2333

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

2322{
2323 iks *content;
2324 unsigned int changed = 0;
2325 struct ast_channel *chan;
2326
2327 /* Look at the content in the session initiation */
2328 for (content = iks_child(iks_child(pak->x)); content; content = iks_next(content)) {
2329 char *name;
2330 struct ast_rtp_instance *rtp = NULL;
2331 iks *description, *transport;
2332
2333 /* Ignore specific parts if they are known not to be useful */
2334 if (!strcmp(iks_name(content), "conference-info")) {
2335 continue;
2336 }
2337
2338 name = iks_find_attrib(content, "name");
2339
2340 if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
2341 /* If this content stanza has no name consider it invalid and move on */
2342 if (ast_strlen_zero(name) && !(name = iks_find_attrib(content, "jin:name"))) {
2344 ast_log(LOG_ERROR, "Received content without a name on session '%s'\n", session->sid);
2345 return -1;
2346 }
2347
2348 /* Try to pre-populate which RTP instance this content is relevant to */
2349 if (!strcmp(session->audio_name, name)) {
2350 rtp = session->rtp;
2351 } else if (!strcmp(session->video_name, name)) {
2352 rtp = session->vrtp;
2353 }
2354 } else {
2355 /* Google-V1 has no concept of associating things like the above does, so since we only support audio over it assume they want audio */
2356 rtp = session->rtp;
2357 }
2358
2359 /* If description information is available use it */
2360 if ((description = iks_find_with_attrib(content, "description", "xmlns", JINGLE_RTP_NS)) ||
2361 (description = iks_find_with_attrib(content, "rtp:description", "xmlns:rtp", JINGLE_RTP_NS)) ||
2362 (description = iks_find_with_attrib(content, "pho:description", "xmlns:pho", GOOGLE_PHONE_NS)) ||
2363 (description = iks_find_with_attrib(pak->query, "description", "xmlns", GOOGLE_PHONE_NS)) ||
2364 (description = iks_find_with_attrib(pak->query, "pho:description", "xmlns:pho", GOOGLE_PHONE_NS)) ||
2365 (description = iks_find_with_attrib(pak->query, "vid:description", "xmlns", GOOGLE_VIDEO_NS))) {
2366 /* If we failed to do something with the content description abort immediately */
2367 if (jingle_interpret_description(session, description, name, &rtp)) {
2368 return -1;
2369 }
2370
2371 /* If we successfully interpret the description then the codecs need updating */
2372 changed = 1;
2373 }
2374
2375 /* If we get past the description handling and we still don't know what RTP instance this is for... it is unknown content */
2376 if (!rtp) {
2377 ast_log(LOG_ERROR, "Received a content stanza but have no RTP instance for it on session '%s'\n", session->sid);
2379 return -1;
2380 }
2381
2382 /* If ICE UDP transport information is available use it */
2383 if ((transport = iks_find_with_attrib(content, "transport", "xmlns", JINGLE_ICE_UDP_NS))) {
2384 if (jingle_interpret_ice_udp_transport(session, transport, rtp)) {
2385 return -1;
2386 }
2387 } else if ((transport = iks_find_with_attrib(content, "transport", "xmlns", GOOGLE_TRANSPORT_NS)) ||
2388 (transport = iks_find_with_attrib(content, "p:transport", "xmlns:p", GOOGLE_TRANSPORT_NS)) ||
2389 (transport = iks_find_with_attrib(pak->x, "session", "xmlns", GOOGLE_SESSION_NS)) ||
2390 (transport = iks_find_with_attrib(pak->x, "ses:session", "xmlns:ses", GOOGLE_SESSION_NS))) {
2391 /* If Google transport support is available use it */
2392 if (jingle_interpret_google_transport(session, transport, rtp)) {
2393 return -1;
2394 }
2395 } else if (iks_find(content, "transport")) {
2396 /* If this is a transport we do not support terminate the session as it probably won't work out in the end */
2398 ast_log(LOG_ERROR, "Unsupported transport type received on session '%s'\n", session->sid);
2399 return -1;
2400 }
2401 }
2402
2403 if (!changed) {
2404 return 0;
2405 }
2406
2407 if ((chan = jingle_session_lock_full(session))) {
2408 struct ast_format_cap *caps;
2409 struct ast_format *fmt;
2410
2412 if (caps) {
2415 ao2_ref(caps, -1);
2416 }
2417
2418 fmt = ast_format_cap_get_format(session->jointcap, 0);
2419 ast_set_read_format(chan, fmt);
2420 ast_set_write_format(chan, fmt);
2421 ao2_ref(fmt, -1);
2422
2423 ast_channel_unlock(chan);
2424 ast_channel_unref(chan);
2425 }
2427
2428 return 0;
2429}
#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:298
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:2162
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:1239
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:2075
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:2243
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:5721
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5762
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 2075 of file chan_motif.c.

2076{
2077 char *media = iks_find_attrib(description, "media");
2078 struct ast_rtp_codecs codecs;
2079 iks *codec;
2080 int othercapability = 0;
2081
2082 /* Google-V1 is always carrying audio, but just doesn't tell us so */
2083 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
2084 media = "audio";
2085 } else if (ast_strlen_zero(media)) {
2087 ast_log(LOG_ERROR, "Received a content description on session '%s' without a name\n", session->sid);
2088 return -1;
2089 }
2090
2091 /* Determine the type of media that is being carried and update the RTP instance, as well as the name */
2092 if (!strcasecmp(media, "audio")) {
2093 if (!ast_strlen_zero(name)) {
2094 ast_string_field_set(session, audio_name, name);
2095 }
2096 *rtp = session->rtp;
2099 } else if (!strcasecmp(media, "video")) {
2100 if (!ast_strlen_zero(name)) {
2101 ast_string_field_set(session, video_name, name);
2102 }
2103
2105 *rtp = session->vrtp;
2106
2107 /* If video is not present cancel this session */
2108 if (!session->vrtp) {
2110 ast_log(LOG_ERROR, "Received a video content description on session '%s' but could not enable video\n", session->sid);
2111 return -1;
2112 }
2113
2116 } else {
2117 /* Unknown media type */
2119 ast_log(LOG_ERROR, "Unsupported media type '%s' received in content description on session '%s'\n", media, session->sid);
2120 return -1;
2121 }
2122
2125 ast_log(LOG_ERROR, "Could not initialize codecs for negotiation on session '%s'\n", session->sid);
2126 return -1;
2127 }
2128
2129 /* Iterate the codecs updating the relevant RTP instance as we go */
2130 for (codec = iks_child(description); codec; codec = iks_next(codec)) {
2131 char *id = iks_find_attrib(codec, "id");
2132 char *attr_name = iks_find_attrib(codec, "name");
2133 char *clockrate = iks_find_attrib(codec, "clockrate");
2134 int rtp_id, rtp_clockrate;
2135
2136 if (!ast_strlen_zero(id) && !ast_strlen_zero(attr_name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
2137 if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
2138 ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, attr_name, 0, rtp_clockrate);
2139 } else {
2140 ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, rtp_id, media, attr_name, 0);
2141 }
2142 }
2143 }
2144
2145 ast_rtp_codecs_payload_formats(&codecs, session->peercap, &othercapability);
2146 ast_format_cap_get_compatible(session->cap, session->peercap, session->jointcap);
2147
2148 if (!ast_format_cap_count(session->jointcap)) {
2149 /* We have no compatible codecs, so terminate the session appropriately */
2152 return -1;
2153 }
2154
2157
2158 return 0;
2159}
static void jingle_enable_video(struct jingle_session *session)
Internal helper function which enables video support on a session if possible.
Definition: chan_motif.c:710
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:1002
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:1279
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:1699
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:986
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:1490
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:1404

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

2244{
2246 iks *candidate;
2247
2248 if (!ice) {
2250 ast_log(LOG_ERROR, "Received Google transport information on session '%s' but ICE support not available\n", session->sid);
2251 return -1;
2252 }
2253
2254 /* If this session has not transitioned to the Google transport do so now */
2255 if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V2) &&
2256 (session->transport != JINGLE_TRANSPORT_GOOGLE_V1)) {
2257 /* Stop built-in ICE support... we need to fall back to the old old old STUN */
2258 ice->stop(rtp);
2259
2261 }
2262
2263 for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
2264 char *address = iks_find_attrib(candidate, "address"), *port = iks_find_attrib(candidate, "port");
2265 char *username = iks_find_attrib(candidate, "username"), *name = iks_find_attrib(candidate, "name");
2266 char *protocol = iks_find_attrib(candidate, "protocol");
2267 int real_port;
2268 struct ast_sockaddr target = { { 0, } };
2269 /* In Google land the combined value is 32 bytes */
2270 char combined[33] = "";
2271
2272 /* If this is NOT actually a candidate just skip it */
2273 if (strcasecmp(iks_name(candidate), "candidate") &&
2274 strcasecmp(iks_name(candidate), "p:candidate") &&
2275 strcasecmp(iks_name(candidate), "ses:candidate")) {
2276 continue;
2277 }
2278
2279 /* If this candidate is incomplete skip it */
2280 if (ast_strlen_zero(address) || ast_strlen_zero(port) || ast_strlen_zero(username) ||
2283 ast_log(LOG_ERROR, "Incomplete Google candidate received on session '%s'\n", session->sid);
2284 return -1;
2285 }
2286
2287 /* We only support UDP so skip any other protocols */
2288 if (!ast_strlen_zero(protocol) && strcasecmp(protocol, "udp")) {
2289 continue;
2290 }
2291
2292 /* We only permit audio and video, not RTCP */
2293 if (strcasecmp(name, "rtp") && strcasecmp(name, "video_rtp")) {
2294 continue;
2295 }
2296
2297 /* Parse the target information so we can send a STUN request to the candidate */
2298 if (sscanf(port, "%30d", &real_port) != 1) {
2300 ast_log(LOG_ERROR, "Invalid Google candidate port '%s' received on session '%s'\n", port, session->sid);
2301 return -1;
2302 }
2304 ast_sockaddr_set_port(&target, real_port);
2305
2306 /* Per the STUN support Google talk uses combine the two usernames */
2307 snprintf(combined, sizeof(combined), "%s%s", username, ice->get_ufrag(rtp));
2308
2309 /* This should appease the masses... we will actually change the remote address when we get their STUN packet */
2310 ast_rtp_instance_stun_request(rtp, &target, combined);
2311 }
2312
2313 return 0;
2314}
#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:2867

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

2163{
2165 char *ufrag = iks_find_attrib(transport, "ufrag"), *pwd = iks_find_attrib(transport, "pwd");
2166 iks *candidate;
2167
2168 if (!ice) {
2170 ast_log(LOG_ERROR, "Received ICE-UDP transport information on session '%s' but ICE support not available\n", session->sid);
2171 return -1;
2172 }
2173
2174 if (!ast_strlen_zero(ufrag) && !ast_strlen_zero(pwd)) {
2175 ice->set_authentication(rtp, ufrag, pwd);
2176 }
2177
2178 for (candidate = iks_child(transport); candidate; candidate = iks_next(candidate)) {
2179 char *component = iks_find_attrib(candidate, "component"), *foundation = iks_find_attrib(candidate, "foundation");
2180 char *generation = iks_find_attrib(candidate, "generation"), *id = iks_find_attrib(candidate, "id");
2181 char *ip = iks_find_attrib(candidate, "ip"), *port = iks_find_attrib(candidate, "port");
2182 char *priority = iks_find_attrib(candidate, "priority"), *protocol = iks_find_attrib(candidate, "protocol");
2183 char *type = iks_find_attrib(candidate, "type");
2184 struct ast_rtp_engine_ice_candidate local_candidate = { 0, };
2185 int real_port;
2186 struct ast_sockaddr remote_address = { { 0, } };
2187
2188 /* If this candidate is incomplete skip it */
2189 if (ast_strlen_zero(component) || ast_strlen_zero(foundation) || ast_strlen_zero(generation) || ast_strlen_zero(id) ||
2191 ast_strlen_zero(protocol) || ast_strlen_zero(type)) {
2193 ast_log(LOG_ERROR, "Incomplete ICE-UDP candidate received on session '%s'\n", session->sid);
2194 return -1;
2195 }
2196
2197 if ((sscanf(component, "%30u", &local_candidate.id) != 1) ||
2198 (sscanf(priority, "%30u", (unsigned *)&local_candidate.priority) != 1) ||
2199 (sscanf(port, "%30d", &real_port) != 1)) {
2201 ast_log(LOG_ERROR, "Invalid ICE-UDP candidate information received on session '%s'\n", session->sid);
2202 return -1;
2203 }
2204
2205 local_candidate.foundation = foundation;
2206 local_candidate.transport = protocol;
2207
2208 ast_sockaddr_parse(&local_candidate.address, ip, PARSE_PORT_FORBID);
2209
2210 /* We only support IPv4 right now */
2211 if (!ast_sockaddr_is_ipv4(&local_candidate.address)) {
2212 continue;
2213 }
2214
2215 ast_sockaddr_set_port(&local_candidate.address, real_port);
2216
2217 if (!strcasecmp(type, "host")) {
2218 local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_HOST;
2219 } else if (!strcasecmp(type, "srflx")) {
2220 local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_SRFLX;
2221 } else if (!strcasecmp(type, "relay")) {
2222 local_candidate.type = AST_RTP_ICE_CANDIDATE_TYPE_RELAYED;
2223 } else {
2224 continue;
2225 }
2226
2227 /* Worst case use the first viable address */
2228 ast_rtp_instance_get_remote_address(rtp, &remote_address);
2229
2230 if (ast_sockaddr_is_ipv4(&local_candidate.address) && ast_sockaddr_isnull(&remote_address)) {
2231 ast_rtp_instance_set_remote_address(rtp, &local_candidate.address);
2232 }
2233
2234 ice->add_remote_candidate(rtp, &local_candidate);
2235 }
2236
2237 ice->start(rtp);
2238
2239 return 0;
2240}
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:1250
#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:1138
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:538
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:542
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:540

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

811{
812 struct ast_channel *chan;
813 const char *str = S_OR(title, session->remote);
814 struct ast_format_cap *caps;
815 struct ast_format *tmpfmt;
816
817 if (!ast_format_cap_count(session->cap)) {
818 return NULL;
819 }
820
822 if (!caps) {
823 return NULL;
824 }
825
826 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)))) {
827 ao2_ref(caps, -1);
828 return NULL;
829 }
830
832
836
837 ast_channel_callid_set(chan, session->callid);
838
841 ao2_ref(caps, -1);
842
843 if (session->rtp) {
844 struct ast_rtp_engine_ice *ice;
845
850
851 if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
852 (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
853 (ice = ast_rtp_instance_get_ice(session->rtp))) {
854 /* We stop built in ICE support because we need to fall back to old old old STUN support */
855 ice->stop(session->rtp);
856 }
857 }
858
859 if (state == AST_STATE_RING) {
860 ast_channel_rings_set(chan, 1);
861 }
862
864
865 tmpfmt = ast_format_cap_get_format(session->cap, 0);
866 ast_channel_set_writeformat(chan, tmpfmt);
867 ast_channel_set_rawwriteformat(chan, tmpfmt);
868 ast_channel_set_readformat(chan, tmpfmt);
869 ast_channel_set_rawreadformat(chan, tmpfmt);
870 ao2_ref(tmpfmt, -1);
871
872 ao2_lock(endpoint);
873
874 ast_channel_callgroup_set(chan, endpoint->callgroup);
876
877 if (!ast_strlen_zero(endpoint->accountcode)) {
878 ast_channel_accountcode_set(chan, endpoint->accountcode);
879 }
880
881 if (!ast_strlen_zero(endpoint->language)) {
882 ast_channel_language_set(chan, endpoint->language);
883 }
884
885 if (!ast_strlen_zero(endpoint->musicclass)) {
886 ast_channel_musicclass_set(chan, endpoint->musicclass);
887 }
888
889 ast_channel_context_set(chan, endpoint->context);
890 if (ast_exists_extension(NULL, endpoint->context, endpoint->name, 1, NULL)) {
891 ast_channel_exten_set(chan, endpoint->name);
892 } else {
893 ast_channel_exten_set(chan, "s");
894 }
896
897 ao2_unlock(endpoint);
898
900 ast_channel_unlock(chan);
901
902 return chan;
903}
const char * str
Definition: app_jack.c:150
static struct ast_channel_tech jingle_tech
PBX interface structure for channel registration.
Definition: chan_motif.c:395
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:1303
@ AST_ADSI_UNAVAILABLE
Definition: channel.h:891
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:4190
#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:325
const ast_string_field musicclass
Definition: chan_motif.c:325
const ast_string_field accountcode
Definition: chan_motif.c:325
const ast_string_field context
Definition: chan_motif.c:325

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

1567{
1568 struct jingle_session *session = data;
1569 iks *error = iks_find(pak->x, "error"), *redirect;
1570
1571 /* In all cases this hook is done with */
1572 iks_filter_remove_rule(session->connection->filter, session->rule);
1573 session->rule = NULL;
1574
1576
1577 /* If no error occurred they accepted our session-initiate message happily */
1578 if (!error) {
1579 struct ast_channel *chan;
1580
1581 if ((chan = jingle_session_lock_full(session))) {
1583 ast_channel_unlock(chan);
1584 ast_channel_unref(chan);
1585 }
1587
1588 jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
1589
1590 goto end;
1591 }
1592
1593 /* Assume that because this is an error the session is gone, there is only one case where this is incorrect - a redirect */
1594 session->gone = 1;
1595
1596 /* Map the error we received to an appropriate cause code and hang up the channel */
1597 if ((redirect = iks_find_with_attrib(error, "redirect", "xmlns", XMPP_STANZAS_NS))) {
1598 iks *to = iks_child(redirect);
1599 char *target;
1600
1601 if (to && (target = iks_name(to)) && !ast_strlen_zero(target)) {
1602 /* Make the xmpp: go away if it is present */
1603 if (!strncmp(target, "xmpp:", 5)) {
1604 target += 5;
1605 }
1606
1607 /* This is actually a fairly simple operation - we update the remote and send another session-initiate */
1608 ast_copy_string(session->remote, target, sizeof(session->remote));
1609
1610 /* Add a new hook so we can get the status of redirected session */
1611 session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1612 IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1613
1615
1616 session->gone = 0;
1617 } else {
1619 }
1620 } else if (iks_find_with_attrib(error, "service-unavailable", "xmlns", XMPP_STANZAS_NS)) {
1622 } else if (iks_find_with_attrib(error, "resource-constraint", "xmlns", XMPP_STANZAS_NS)) {
1624 } else if (iks_find_with_attrib(error, "bad-request", "xmlns", XMPP_STANZAS_NS)) {
1626 } else if (iks_find_with_attrib(error, "remote-server-not-found", "xmlns", XMPP_STANZAS_NS)) {
1628 } else if (iks_find_with_attrib(error, "feature-not-implemented", "xmlns", XMPP_STANZAS_NS)) {
1629 /* Assume that this occurred because the remote side does not support our transport, so drop it down one and try again */
1630 session->transport--;
1631
1632 /* If we still have a viable transport mechanism re-send the session-initiate */
1633 if (session->transport != JINGLE_TRANSPORT_NONE) {
1634 struct ast_rtp_engine_ice *ice;
1635
1636 if (((session->transport == JINGLE_TRANSPORT_GOOGLE_V2) ||
1637 (session->transport == JINGLE_TRANSPORT_GOOGLE_V1)) &&
1638 (ice = ast_rtp_instance_get_ice(session->rtp))) {
1639 /* We stop built in ICE support because we need to fall back to old old old STUN support */
1640 ice->stop(session->rtp);
1641 }
1642
1643 /* Re-send the message to the *original* target and not a redirected one */
1644 ast_copy_string(session->remote, session->remote_original, sizeof(session->remote));
1645
1646 session->rule = iks_filter_add_rule(session->connection->filter, jingle_outgoing_hook, session,
1647 IKS_RULE_ID, session->connection->mid, IKS_RULE_DONE);
1648
1650
1651 session->gone = 0;
1652 } else {
1653 /* Otherwise we have exhausted all transports */
1655 }
1656 } else {
1658 }
1659
1660end:
1662
1663 return IKS_FILTER_EAT;
1664}
#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:301
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 1239 of file chan_motif.c.

1240{
1241 struct ast_channel *chan;
1242
1243 if ((chan = jingle_session_lock_full(session))) {
1244 ast_debug(3, "Hanging up channel '%s' with cause '%d'\n", ast_channel_name(chan), cause);
1245 ast_queue_hangup_with_cause(chan, cause);
1246 ast_channel_unlock(chan);
1247 ast_channel_unref(chan);
1248 }
1250}

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

1683{
1685 struct ast_frame *frame = &ast_null_frame;
1686
1687 switch (ast_channel_fdno(ast)) {
1688 case 0:
1689 if (session->rtp) {
1690 frame = ast_rtp_instance_read(session->rtp, 0);
1691 }
1692 break;
1693 case 1:
1694 if (session->rtp) {
1695 frame = ast_rtp_instance_read(session->rtp, 1);
1696 }
1697 break;
1698 case 2:
1699 if (session->vrtp) {
1700 frame = ast_rtp_instance_read(session->vrtp, 0);
1701 }
1702 break;
1703 case 3:
1704 if (session->vrtp) {
1705 frame = ast_rtp_instance_read(session->vrtp, 1);
1706 }
1707 break;
1708 default:
1709 break;
1710 }
1711
1712 if (frame && frame->frametype == AST_FRAME_VOICE &&
1715 ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
1717 ast_frfree(frame);
1718 frame = &ast_null_frame;
1719 } else {
1720 struct ast_format_cap *caps;
1721
1722 ast_debug(1, "Oooh, format changed to %s\n",
1724
1726 if (caps) {
1727 ast_format_cap_append(caps, frame->subclass.format, 0);
1729 ao2_ref(caps, -1);
1730 }
1733 }
1734 }
1735
1736 return frame;
1737}
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:606
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 1946 of file chan_motif.c.

1947{
1949 RAII_VAR(struct jingle_endpoint *, endpoint, NULL, ao2_cleanup);
1950 char *dialed, target[1024] = "";
1951 struct ast_xmpp_buddy *buddy;
1952 struct jingle_session *session;
1953 struct ast_channel *chan;
1954 enum jingle_transport transport = JINGLE_TRANSPORT_NONE;
1955 struct ast_rtp_engine_ice *ice;
1958 AST_APP_ARG(target);
1959 );
1960
1961 /* We require at a minimum one audio format to be requested */
1963 ast_log(LOG_ERROR, "Motif channel driver requires an audio format when dialing a destination\n");
1965 return NULL;
1966 }
1967
1968 if (ast_strlen_zero(data) || !(dialed = ast_strdupa(data))) {
1969 ast_log(LOG_ERROR, "Unable to create channel with empty destination.\n");
1971 return NULL;
1972 }
1973
1974 /* Parse the given dial string and validate the results */
1975 AST_NONSTANDARD_APP_ARGS(args, dialed, '/');
1976
1977 if (ast_strlen_zero(args.name) || ast_strlen_zero(args.target)) {
1978 ast_log(LOG_ERROR, "Unable to determine endpoint name and target.\n");
1980 return NULL;
1981 }
1982
1983 if (!(endpoint = jingle_endpoint_find(cfg->endpoints, args.name))) {
1984 ast_log(LOG_ERROR, "Endpoint '%s' does not exist.\n", args.name);
1986 return NULL;
1987 }
1988
1989 ao2_lock(endpoint->state);
1990
1991 /* If we don't have a connection for the endpoint we can't exactly start a session on it */
1992 if (!endpoint->connection) {
1993 ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s' as no valid connection exists\n", args.name);
1995 ao2_unlock(endpoint->state);
1996 return NULL;
1997 }
1998
1999 /* Find the target in the roster so we can choose a resource */
2000 if ((buddy = ao2_find(endpoint->connection->buddies, args.target, OBJ_KEY))) {
2001 struct ao2_iterator res;
2003
2004 /* Iterate through finding the first viable Jingle capable resource */
2005 res = ao2_iterator_init(buddy->resources, 0);
2006 while ((resource = ao2_iterator_next(&res))) {
2007 if (resource->caps.jingle) {
2008 snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
2009 transport = JINGLE_TRANSPORT_ICE_UDP;
2010 break;
2011 } else if (resource->caps.google) {
2012 snprintf(target, sizeof(target), "%s/%s", args.target, resource->resource);
2013 transport = JINGLE_TRANSPORT_GOOGLE_V2;
2014 break;
2015 }
2016 ao2_ref(resource, -1);
2017 }
2019
2020 ao2_ref(buddy, -1);
2021 } else {
2022 /* If the target is NOT in the roster use the provided target as-is */
2023 ast_copy_string(target, args.target, sizeof(target));
2024 }
2025
2026 ao2_unlock(endpoint->state);
2027
2028 /* If no target was found we can't set up a session */
2029 if (ast_strlen_zero(target)) {
2030 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);
2032 return NULL;
2033 }
2034
2035 if (!(session = jingle_alloc(endpoint, target, NULL))) {
2036 ast_log(LOG_ERROR, "Unable to create Jingle session on endpoint '%s'\n", args.name);
2038 return NULL;
2039 }
2040
2041 /* Update the transport if we learned what we should actually use */
2042 if (transport != JINGLE_TRANSPORT_NONE) {
2043 session->transport = transport;
2044 /* Note that for Google-V1 and Google-V2 we don't stop built-in ICE support, this will happen in jingle_new */
2045 }
2046
2047 if (!(chan = jingle_new(endpoint, session, AST_STATE_DOWN, target, assignedids, requestor, NULL))) {
2048 ast_log(LOG_ERROR, "Unable to create Jingle channel on endpoint '%s'\n", args.name);
2050 ao2_ref(session, -1);
2051 return NULL;
2052 }
2053
2054 /* If video was requested try to enable it on the session */
2057 }
2058
2059 /* As this is outgoing set ourselves as controlling */
2060 if (session->rtp && (ice = ast_rtp_instance_get_ice(session->rtp))) {
2061 ice->ice_lite(session->rtp);
2062 }
2063
2064 if (session->vrtp && (ice = ast_rtp_instance_get_ice(session->vrtp))) {
2065 ice->ice_lite(session->vrtp);
2066 }
2067
2068 /* We purposely don't decrement the session here as there is a reference on the channel */
2069 ao2_link(endpoint->state->sessions, session);
2070
2071 return chan;
2072}
#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:552
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 926 of file chan_motif.c.

927{
928 iks *response, *error = NULL, *reason = NULL, *reason2 = NULL;
929
930 if (!(response = iks_new("iq")) ||
931 !(error = iks_new("error")) ||
932 !(reason = iks_new(reasonstr))) {
933 ast_log(LOG_ERROR, "Unable to allocate IKS error response stanzas\n");
934 goto end;
935 }
936
937 iks_insert_attrib(response, "type", "error");
938 iks_insert_attrib(response, "from", connection->jid->full);
939 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
940 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
941
942 iks_insert_attrib(error, "type", type);
943 iks_insert_node(error, reason);
944
945 if (!ast_strlen_zero(reasonstr2) && (reason2 = iks_new(reasonstr2))) {
946 iks_insert_node(error, reason2);
947 }
948
949 iks_insert_node(response, error);
950
951 ast_xmpp_client_send(connection, response);
952end:
953 iks_delete(reason2);
954 iks_delete(reason);
955 iks_delete(error);
956 iks_delete(response);
957}
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:2663

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

907{
908 iks *response;
909
910 if (!(response = iks_new("iq"))) {
911 ast_log(LOG_ERROR, "Unable to allocate an IKS response stanza\n");
912 return;
913 }
914
915 iks_insert_attrib(response, "type", "result");
916 iks_insert_attrib(response, "from", connection->jid->full);
917 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
918 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
919
920 ast_xmpp_client_send(connection, response);
921
922 iks_delete(response);
923}

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

1561{
1562 jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "accept" : "session-accept");
1563}
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:1472

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

1473{
1474 iks *iq, *jingle, *audio = NULL, *audio_description = NULL, *video = NULL, *video_description = NULL;
1475 iks *audio_payloads[session->maxpayloads], *video_payloads[session->maxpayloads];
1476 iks *audio_transport = NULL, *video_transport = NULL;
1477 int i, res = 0;
1478
1479 if (!(iq = iks_new("iq")) ||
1480 !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
1482 iks_delete(iq);
1483 return;
1484 }
1485
1486 memset(audio_payloads, 0, sizeof(audio_payloads));
1487 memset(video_payloads, 0, sizeof(video_payloads));
1488
1489 iks_insert_attrib(iq, "from", session->connection->jid->full);
1490 iks_insert_attrib(iq, "to", session->remote);
1491 iks_insert_attrib(iq, "type", "set");
1492 iks_insert_attrib(iq, "id", session->connection->mid);
1493 ast_xmpp_increment_mid(session->connection->mid);
1494
1495 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1496 iks_insert_attrib(jingle, "type", action);
1497 iks_insert_attrib(jingle, "id", session->sid);
1498 iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1499 } else {
1500 iks_insert_attrib(jingle, "action", action);
1501 iks_insert_attrib(jingle, "sid", session->sid);
1502 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1503 }
1504
1505 if (!strcasecmp(action, "session-initiate") || !strcasecmp(action, "initiate") || !strcasecmp(action, "accept")) {
1506 iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
1507 }
1508
1509 iks_insert_node(iq, jingle);
1510
1511 if (session->rtp && (audio = iks_new("content")) && (audio_description = iks_new("description")) &&
1512 (audio_transport = iks_new("transport"))) {
1513 res = jingle_add_content(session, jingle, audio, audio_description, audio_transport, session->audio_name,
1514 AST_MEDIA_TYPE_AUDIO, session->rtp, audio_payloads);
1515 } else {
1516 ast_log(LOG_ERROR, "Failed to allocate audio content stanzas for session '%s', hanging up\n", session->sid);
1517 res = -1;
1518 }
1519
1520 if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
1521 if ((video = iks_new("content")) && (video_description = iks_new("description")) &&
1522 (video_transport = iks_new("transport"))) {
1523 res = jingle_add_content(session, jingle, video, video_description, video_transport, session->video_name,
1524 AST_MEDIA_TYPE_VIDEO, session->vrtp, video_payloads);
1525 } else {
1526 ast_log(LOG_ERROR, "Failed to allocate video content stanzas for session '%s', hanging up\n", session->sid);
1527 res = -1;
1528 }
1529 }
1530
1531 if (!res) {
1532 ast_xmpp_client_send(session->connection, iq);
1533 } else {
1535 }
1536
1537 iks_delete(video_transport);
1538 iks_delete(audio_transport);
1539
1540 for (i = 0; i < session->maxpayloads; i++) {
1541 iks_delete(video_payloads[i]);
1542 iks_delete(audio_payloads[i]);
1543 }
1544
1545 iks_delete(video_description);
1546 iks_delete(video);
1547 iks_delete(audio_description);
1548 iks_delete(audio);
1549 iks_delete(jingle);
1550 iks_delete(iq);
1551}
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:1434
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
Definition: res_xmpp.c:1154

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

1141{
1142 iks *iq = NULL, *jingle = NULL, *text = NULL;
1143
1144 /* Google-V1 has no way to send informational messages so don't even bother trying */
1145 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1146 return;
1147 }
1148
1149 if (!(iq = iks_new("iq")) || !(jingle = iks_new("jingle")) || !(text = iks_new(info))) {
1150 ast_log(LOG_ERROR, "Failed to allocate stanzas for session-info message on session '%s'\n", session->sid);
1151 goto end;
1152 }
1153
1154 iks_insert_attrib(iq, "to", session->remote);
1155 iks_insert_attrib(iq, "type", "set");
1156 iks_insert_attrib(iq, "id", session->connection->mid);
1157 ast_xmpp_increment_mid(session->connection->mid);
1158
1159 iks_insert_attrib(jingle, "action", "session-info");
1160 iks_insert_attrib(jingle, "sid", session->sid);
1161 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1162 iks_insert_node(iq, jingle);
1163 iks_insert_node(jingle, text);
1164
1165 ast_xmpp_client_send(session->connection, iq);
1166
1167end:
1168 iks_delete(text);
1169 iks_delete(jingle);
1170 iks_delete(iq);
1171}
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-initiate message.

Definition at line 1554 of file chan_motif.c.

1555{
1556 jingle_send_session_action(session, session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "initiate" : "session-initiate");
1557}

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

1101{
1102 iks *iq = NULL, *jingle = NULL, *reason = NULL, *text = NULL;
1103
1104 if (!(iq = iks_new("iq")) || !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle")) ||
1105 !(reason = iks_new("reason")) || !(text = iks_new(reasontext))) {
1106 ast_log(LOG_ERROR, "Failed to allocate stanzas for session-terminate message on session '%s'\n", session->sid);
1107 goto end;
1108 }
1109
1110 iks_insert_attrib(iq, "to", session->remote);
1111 iks_insert_attrib(iq, "type", "set");
1112 iks_insert_attrib(iq, "id", session->connection->mid);
1113 ast_xmpp_increment_mid(session->connection->mid);
1114
1115 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1116 iks_insert_attrib(jingle, "type", "terminate");
1117 iks_insert_attrib(jingle, "id", session->sid);
1118 iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1119 iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : session->remote);
1120 } else {
1121 iks_insert_attrib(jingle, "action", "session-terminate");
1122 iks_insert_attrib(jingle, "sid", session->sid);
1123 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1124 }
1125
1126 iks_insert_node(iq, jingle);
1127 iks_insert_node(jingle, reason);
1128 iks_insert_node(reason, text);
1129
1130 ast_xmpp_client_send(session->connection, iq);
1131
1132end:
1133 iks_delete(text);
1134 iks_delete(reason);
1135 iks_delete(jingle);
1136 iks_delete(iq);
1137}

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

1254{
1255 iks *iq, *jingle = NULL, *audio = NULL, *audio_transport = NULL, *video = NULL, *video_transport = NULL;
1256 iks *audio_candidates[session->maxicecandidates], *video_candidates[session->maxicecandidates];
1257 int i, res = 0;
1258
1259 if (!(iq = iks_new("iq")) ||
1260 !(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
1261 iks_delete(iq);
1263 ast_log(LOG_ERROR, "Failed to allocate stanzas for transport-info message, hanging up session '%s'\n", session->sid);
1264 return;
1265 }
1266
1267 memset(audio_candidates, 0, sizeof(audio_candidates));
1268 memset(video_candidates, 0, sizeof(video_candidates));
1269
1270 iks_insert_attrib(iq, "from", session->connection->jid->full);
1271 iks_insert_attrib(iq, "to", from);
1272 iks_insert_attrib(iq, "type", "set");
1273 iks_insert_attrib(iq, "id", session->connection->mid);
1274 ast_xmpp_increment_mid(session->connection->mid);
1275
1276 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1277 iks_insert_attrib(jingle, "type", "candidates");
1278 iks_insert_attrib(jingle, "id", session->sid);
1279 iks_insert_attrib(jingle, "xmlns", GOOGLE_SESSION_NS);
1280 iks_insert_attrib(jingle, "initiator", session->outgoing ? session->connection->jid->full : from);
1281 } else {
1282 iks_insert_attrib(jingle, "action", "transport-info");
1283 iks_insert_attrib(jingle, "sid", session->sid);
1284 iks_insert_attrib(jingle, "xmlns", JINGLE_NS);
1285 }
1286 iks_insert_node(iq, jingle);
1287
1288 if (session->rtp) {
1289 if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
1290 /* V1 protocol has the candidates directly in the session */
1291 res = jingle_add_google_candidates_to_transport(session->rtp, jingle, audio_candidates, 0, session->transport, session->maxicecandidates);
1292 } else if ((audio = iks_new("content")) && (audio_transport = iks_new("transport"))) {
1293 iks_insert_attrib(audio, "creator", session->outgoing ? "initiator" : "responder");
1294 iks_insert_attrib(audio, "name", session->audio_name);
1295 iks_insert_node(jingle, audio);
1296 iks_insert_node(audio, audio_transport);
1297
1298 if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1299 res = jingle_add_ice_udp_candidates_to_transport(session->rtp, audio_transport, audio_candidates, session->maxicecandidates);
1300 } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1301 res = jingle_add_google_candidates_to_transport(session->rtp, audio_transport, audio_candidates, 0, session->transport,
1302 session->maxicecandidates);
1303 }
1304 } else {
1305 res = -1;
1306 }
1307 }
1308
1309 if ((session->transport != JINGLE_TRANSPORT_GOOGLE_V1) && !res && session->vrtp) {
1310 if ((video = iks_new("content")) && (video_transport = iks_new("transport"))) {
1311 iks_insert_attrib(video, "creator", session->outgoing ? "initiator" : "responder");
1312 iks_insert_attrib(video, "name", session->video_name);
1313 iks_insert_node(jingle, video);
1314 iks_insert_node(video, video_transport);
1315
1316 if (session->transport == JINGLE_TRANSPORT_ICE_UDP) {
1317 res = jingle_add_ice_udp_candidates_to_transport(session->vrtp, video_transport, video_candidates, session->maxicecandidates);
1318 } else if (session->transport == JINGLE_TRANSPORT_GOOGLE_V2) {
1319 res = jingle_add_google_candidates_to_transport(session->vrtp, video_transport, video_candidates, 1, session->transport,
1320 session->maxicecandidates);
1321 }
1322 } else {
1323 res = -1;
1324 }
1325 }
1326
1327 if (!res) {
1328 ast_xmpp_client_send(session->connection, iq);
1329 } else {
1331 }
1332
1333 /* Clean up after ourselves */
1334 for (i = 0; i < session->maxicecandidates; i++) {
1335 iks_delete(video_candidates[i]);
1336 iks_delete(audio_candidates[i]);
1337 }
1338
1339 iks_delete(video_transport);
1340 iks_delete(video);
1341 iks_delete(audio_transport);
1342 iks_delete(audio);
1343 iks_delete(jingle);
1344 iks_delete(iq);
1345}
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:1022
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:960

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

1861{
1863
1864 return ast_xmpp_client_send_message(session->connection, session->remote, text);
1865}
int ast_xmpp_client_send_message(struct ast_xmpp_client *client, const char *user, const char *message)
Send a message to a given user using an established XMPP client connection.
Definition: res_xmpp.c:1067

References 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 466 of file chan_motif.c.

467{
468 struct jingle_session *session1 = obj, *session2 = arg;
469 const char *sid = arg;
470
471 return !strcmp(session1->sid, flags & OBJ_KEY ? sid : session2->sid) ? CMP_MATCH | CMP_STOP : 0;
472}
const ast_string_field sid
Definition: chan_motif.c:343

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

604{
605 struct jingle_session *session = obj;
606
607 if (session->rule) {
608 iks_filter_remove_rule(session->connection->filter, session->rule);
609 }
610
611 if (session->connection) {
612 ast_xmpp_client_unref(session->connection);
613 }
614
615 if (session->rtp) {
618 }
619
620 if (session->vrtp) {
623 }
624
625 ao2_cleanup(session->cap);
626 ao2_cleanup(session->jointcap);
627 ao2_cleanup(session->peercap);
628
630}
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:464
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
Definition: rtp_engine.c:2365

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

458{
459 const struct jingle_session *session = obj;
460 const char *sid = obj;
461
462 return ast_str_hash(flags & OBJ_KEY ? sid : session->sid);
463}

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

1191{
1192 struct ast_channel *chan;
1193
1194 /* Locking is simple when it is done right. If you see a deadlock resulting
1195 * in this function, it is not this function's fault, Your problem exists elsewhere.
1196 * This function is perfect... seriously. */
1197 for (;;) {
1198 /* First, get the channel and grab a reference to it */
1199 ao2_lock(pvt);
1200 chan = pvt->owner;
1201 if (chan) {
1202 /* The channel can not go away while we hold the pvt lock.
1203 * Give the channel a ref so it will not go away after we let
1204 * the pvt lock go. */
1205 ast_channel_ref(chan);
1206 } else {
1207 /* no channel, return pvt locked */
1208 return NULL;
1209 }
1210
1211 /* We had to hold the pvt lock while getting a ref to the owner channel
1212 * but now we have to let this lock go in order to preserve proper
1213 * locking order when grabbing the channel lock */
1214 ao2_unlock(pvt);
1215
1216 /* Look, no deadlock avoidance, hooray! */
1217 ast_channel_lock(chan);
1218 ao2_lock(pvt);
1219 if (pvt->owner == chan) {
1220 /* done */
1221 break;
1222 }
1223
1224 /* If the owner changed while everything was unlocked, no problem,
1225 * just start over and everything will work. This is rare, do not be
1226 * confused by this loop and think this it is an expensive operation.
1227 * The majority of the calls to this function will never involve multiple
1228 * executions of this loop. */
1229 ast_channel_unlock(chan);
1230 ast_channel_unref(chan);
1231 ao2_unlock(pvt);
1232 }
1233
1234 /* If owner exists, it is locked and reffed */
1235 return pvt->owner;
1236}
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
struct ast_channel * owner
Definition: chan_motif.c:352

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

699{
700 session->owner = chan;
701 if (session->rtp) {
703 }
704 if (session->vrtp) {
706 }
707}

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

685{
686 return -1;
687}

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

1741{
1743 int res = 0;
1744
1745 switch (frame->frametype) {
1746 case AST_FRAME_VOICE:
1748 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1749
1751 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1752 ast_format_get_name(frame->subclass.format),
1756 return 0;
1757 }
1758 if (session && session->rtp) {
1759 res = ast_rtp_instance_write(session->rtp, frame);
1760 }
1761 break;
1762 case AST_FRAME_VIDEO:
1763 if (session && session->vrtp) {
1764 res = ast_rtp_instance_write(session->vrtp, frame);
1765 }
1766 break;
1767 default:
1768 ast_log(LOG_WARNING, "Can't send %u type frames with Jingle write\n",
1769 frame->frametype);
1770 return 0;
1771 }
1772
1773 return res;
1774}
#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:596
#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 2769 of file chan_motif.c.

2770{
2773 }
2774
2775 if (aco_info_init(&cfg_info)) {
2776 ast_log(LOG_ERROR, "Unable to initialize configuration for chan_motif.\n");
2777 goto end;
2778 }
2779
2780 aco_option_register(&cfg_info, "context", ACO_EXACT, endpoint_options, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, context));
2784 aco_option_register(&cfg_info, "musicclass", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, musicclass));
2785 aco_option_register(&cfg_info, "parkinglot", ACO_EXACT, endpoint_options, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct jingle_endpoint, parkinglot));
2787 aco_option_register(&cfg_info, "allow", ACO_EXACT, endpoint_options, "ulaw,alaw", OPT_CODEC_T, 1, FLDSET(struct jingle_endpoint, cap));
2788 aco_option_register(&cfg_info, "disallow", ACO_EXACT, endpoint_options, "all", OPT_CODEC_T, 0, FLDSET(struct jingle_endpoint, cap));
2792 FLDSET(struct jingle_endpoint, maxicecandidates), DEFAULT_MAX_ICE_CANDIDATES);
2794 FLDSET(struct jingle_endpoint, maxpayloads), DEFAULT_MAX_PAYLOADS);
2795
2797
2798 if (aco_process_config(&cfg_info, 0)) {
2799 ast_log(LOG_ERROR, "Unable to read config file motif.conf. Module loaded but not running.\n");
2800 aco_info_destroy(&cfg_info);
2804 }
2805
2806 if (!(sched = ast_sched_context_create())) {
2807 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2808 goto end;
2809 }
2810
2812 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2813 goto end;
2814 }
2815
2817
2819 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
2820 goto end;
2821 }
2822
2823 return 0;
2824
2825end:
2827
2828 if (sched) {
2830 }
2831
2832 aco_info_destroy(&cfg_info);
2834
2837
2839}
#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:348
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:497
#define DEFAULT_MAX_PAYLOADS
Default maximum number of payloads we will offer.
Definition: chan_motif.c:265
static int custom_group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for groups.
Definition: chan_motif.c:2700
#define DEFAULT_MAX_ICE_CANDIDATES
Default maximum number of ICE candidates we will offer.
Definition: chan_motif.c:262
struct aco_type * endpoint_options[]
Definition: chan_motif.c:595
static int custom_transport_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for transport.
Definition: chan_motif.c:2741
static const char channel_type[]
Definition: chan_motif.c:363
static struct ast_rtp_glue jingle_rtp_glue
Local glue for interacting with the RTP engine core.
Definition: chan_motif.c:690
static int custom_connection_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Custom handler for connection.
Definition: chan_motif.c:2716
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:538
@ 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:905
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:414
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:652

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

2843{
2844 if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
2845 return -1;
2846 }
2847
2848 return 0;
2849}
@ 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 2852 of file chan_motif.c.

2853{
2859 aco_info_destroy(&cfg_info);
2861
2862 return 0;
2863}
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:569

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2872 of file chan_motif.c.

◆ channel_type

const char channel_type[] = "Motif"
static

Definition at line 363 of file chan_motif.c.

Referenced by load_module().

◆ endpoint_option

struct aco_type endpoint_option
static

Definition at line 585 of file chan_motif.c.

◆ endpoint_options

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

Definition at line 595 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:585
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.

Definition at line 597 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 690 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 395 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 371 of file chan_motif.c.