Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
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.
 
#define DEFAULT_MAX_PAYLOADS   "30"
 Default maximum number of payloads we will offer.
 
#define ENDPOINT_BUCKETS   37
 Number of buckets for endpoints.
 
#define GOOGLE_PHONE_NS   "http://www.google.com/session/phone"
 Namespace for Google Phone description.
 
#define GOOGLE_SESSION_NS   "http://www.google.com/session"
 Namespace for Google Session.
 
#define GOOGLE_TRANSPORT_NS   "http://www.google.com/transport/p2p"
 Namespace for Google Talk ICE-UDP.
 
#define GOOGLE_TRANSPORT_RAW_NS   "http://www.google.com/transport/raw-udp"
 Namespace for Google Talk Raw UDP.
 
#define GOOGLE_VIDEO_NS   "http://www.google.com/session/video"
 Namespace for Google Video description.
 
#define JINGLE_ICE_UDP_NS   "urn:xmpp:jingle:transports:ice-udp:1"
 Namespace for Jingle ICE-UDP.
 
#define JINGLE_NS   "urn:xmpp:jingle:1"
 Namespace for Jingle itself.
 
#define JINGLE_RTP_INFO_NS   "urn:xmpp:jingle:apps:rtp:info:1"
 Namespace for Jingle RTP info.
 
#define JINGLE_RTP_NS   "urn:xmpp:jingle:apps:rtp:1"
 Namespace for Jingle RTP sessions.
 
#define SESSION_BUCKETS   37
 Number of buckets for sessions, on a per-endpoint basis.
 
#define XMPP_STANZAS_NS   "urn:ietf:params:xml:ns:xmpp-stanzas"
 Namespace for XMPP stanzas.
 

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.
 
static int custom_group_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Custom handler for groups.
 
static int custom_transport_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Custom handler for transport.
 
static int jingle_action_hook (void *data, ikspak *pak)
 Callback for when a Jingle action is received from an endpoint.
 
static void jingle_action_session_accept (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'session-accept' action.
 
static void jingle_action_session_info (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'session-info' action.
 
static void jingle_action_session_initiate (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Action handlers.
 
static void jingle_action_session_terminate (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'session-terminate' action.
 
static void jingle_action_transport_info (struct jingle_endpoint *endpoint, struct jingle_session *session, ikspak *pak)
 Handler function for the 'transport-info' action.
 
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.
 
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.
 
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.
 
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.
 
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.
 
static int jingle_answer (struct ast_channel *ast)
 Function called by core when we should answer a Jingle session.
 
static int jingle_call (struct ast_channel *ast, const char *dest, int timeout)
 Function called by core to actually start calling a remote party.
 
static void * jingle_config_alloc (void)
 Allocator called when module configuration should appear.
 
static void jingle_config_destructor (void *obj)
 Destructor called when module configuration goes away.
 
static int jingle_digit_begin (struct ast_channel *chan, char digit)
 Function called by core to start a DTMF digit.
 
static int jingle_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 Function called by core to stop a DTMF digit.
 
static void jingle_enable_video (struct jingle_session *session)
 Internal helper function which enables video support on a session if possible.
 
static void * jingle_endpoint_alloc (const char *cat)
 Allocator function for Jingle endpoints.
 
static int jingle_endpoint_cmp (void *obj, void *arg, int flags)
 Comparator function for Jingle endpoints.
 
static void jingle_endpoint_destructor (void *obj)
 Destructor for Jingle endpoints.
 
static void * jingle_endpoint_find (struct ao2_container *tmp_container, const char *category)
 Find function for Jingle endpoints.
 
static int jingle_endpoint_hash (const void *obj, const int flags)
 Hashing function for Jingle endpoints.
 
static struct jingle_endpoint_statejingle_endpoint_state_create (void)
 Allocator function for Jingle endpoint state.
 
static void jingle_endpoint_state_destructor (void *obj)
 Destructor for Jingle endpoint state.
 
static struct jingle_endpoint_statejingle_endpoint_state_find_or_create (const char *category)
 State find/create function.
 
static int jingle_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 Function called by core to change the underlying owner channel.
 
static void jingle_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
 Function called by RTP engine to get peer capabilities.
 
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.
 
static int jingle_hangup (struct ast_channel *ast)
 Function called by core to hang up a Jingle session.
 
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.
 
static int jingle_interpret_content (struct jingle_session *session, ikspak *pak)
 Helper function which locates content stanzas and interprets them.
 
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.
 
static int jingle_interpret_google_transport (struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
 Helper function which handles Google transport information.
 
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.
 
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.
 
static int jingle_outgoing_hook (void *data, ikspak *pak)
 Callback for when a response is received for an outgoing session-initiate message.
 
static void jingle_queue_hangup_with_cause (struct jingle_session *session, int cause)
 Helper function which queues a hangup frame with cause code.
 
static struct ast_framejingle_read (struct ast_channel *ast)
 Function called by core to read any waiting frames.
 
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.
 
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.
 
static void jingle_send_response (struct ast_xmpp_client *connection, ikspak *pak)
 Internal helper function which sends a response.
 
static void jingle_send_session_accept (struct jingle_session *session)
 Internal function which sends a session-accept message.
 
static void jingle_send_session_action (struct jingle_session *session, const char *action)
 Internal function which sends a complete session message.
 
static void jingle_send_session_info (struct jingle_session *session, const char *info)
 Internal function which sends a session-info message.
 
static void jingle_send_session_initiate (struct jingle_session *session)
 Internal function which sends a session-initiate message.
 
static void jingle_send_session_terminate (struct jingle_session *session, const char *reasontext)
 Internal function which sends a session-terminate message.
 
static void jingle_send_transport_info (struct jingle_session *session, const char *from)
 Internal function which sends a transport-info message.
 
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.
 
static int jingle_session_cmp (void *obj, void *arg, int flags)
 Comparator function for Jingle sessions.
 
static void jingle_session_destructor (void *obj)
 Destructor for Jingle sessions.
 
static int jingle_session_hash (const void *obj, const int flags)
 Hashing function for Jingle sessions.
 
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.
 
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.
 
static int jingle_write (struct ast_channel *ast, struct ast_frame *frame)
 Function called by core to write frames.
 
static int load_module (void)
 Load the module.
 
static int reload (void)
 Reload module.
 
static int unload_module (void)
 Unload the jingle channel from Asterisk.
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Motif Jingle Channel Driver" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_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.
 
static struct ast_channel_tech jingle_tech
 PBX interface structure for channel registration.
 
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.
#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:7605
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:2290
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition logger.c:2309
#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:703

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)
static int jingle_interpret_content(struct jingle_session *session, ikspak *pak)
Helper function which locates content stanzas and interprets them.
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:1270
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3018
#define ast_channel_unlock(chan)
Definition channel.h:2983
@ AST_CONTROL_ANSWER
Main Channel structure associated with a channel.
struct ast_endpoint * endpoint

References ao2_unlock, ast_channel_unlock, ast_channel_unref, AST_CONTROL_ANSWER, ast_queue_control(), ast_channel::endpoint, 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:1255
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition channel.c:1230
ast_channel_state
ast_channel states
@ AST_STATE_RINGING
@ AST_STATE_UP
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition channel.c:7373
@ 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, ast_channel::endpoint, 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.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2513
#define ast_channel_lock(chan)
Definition channel.h:2982
@ AST_STATE_RING
@ AST_STATE_DOWN
@ 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:4729
enum ast_endpoint_state state

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, ast_channel::endpoint, 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, and ast_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:1768
#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:1277
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition channel.c:1205
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:4315
#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

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 ast_channel::endpoint, 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.
#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[]
@ 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.
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:2348

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.
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.
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.
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 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 callid from the thread
Definition logger.c:2268
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition logger.c:2263
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.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
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.
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.
static int jingle_outgoing_hook(void *data, ikspak *pak)
Callback for when a response is received for an outgoing session-initiate message.

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.

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)

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:2398
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.
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)
void(* stop)(struct ast_rtp_instance *instance)
Definition rtp_engine.h:544
void(* start)(struct ast_rtp_instance *instance)
Definition rtp_engine.h:542

References ast_channel_set_fd(), ast_channel_uniqueid(), ast_format_cap_get_framing(), ast_format_cap_has_type(), AST_MEDIA_TYPE_VIDEO, ast_rtp_codecs_set_framing(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_ice(), ast_rtp_instance_new(), ast_rtp_instance_set_channel_id(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_RTCP, ast_sockaddr_parse(), JINGLE_TRANSPORT_GOOGLE_V2, NULL, session, ast_rtp_engine_ice::start, 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
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}
#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, and SESSION_BUCKETS.

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:978

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.
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.
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition channel.c:2430
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_CONGESTION
@ 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:7753
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7763
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.
void ast_rtp_instance_update_source(struct ast_rtp_instance *instance)
Indicate that the RTP marker bit should be set on an RTP stream.

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.
static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
Helper function which queues a hangup frame with cause code.
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.
static int jingle_interpret_google_transport(struct jingle_session *session, iks *transport, struct ast_rtp_instance *rtp)
Helper function which handles Google transport information.
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:5732
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition channel.c:5773
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)
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.
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, struct ast_format_cap *astformats, int *nonastformats)
Retrieve all formats that were found.
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.
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.

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.

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, ast_rtp_engine_ice::start, 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
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.
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition rtp_engine.h:538
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
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)) {
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:4196
#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::start, 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,...)

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::start, 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)
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.
static struct @519 args
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

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, ast_channel::endpoint, 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, session, and ast_rtp_engine_ice::start.

◆ 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, ast_rtp_engine_ice::start, 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, LOG_ERROR, and ast_rtp_engine_ice::start.

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.

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

References ast_log, ast_xmpp_client_send(), ast_xmpp_increment_mid(), end, 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.
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.

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:3007
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
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.
#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.
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.
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition channel.c:539
@ ACO_EXACT
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_CODEC_T
Type for default option handler for format capabilities.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition format_cap.c:216
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_rtp_glue_register(glue)
Definition rtp_engine.h: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, jingle_endpoint::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:570

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

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Motif Jingle Channel Driver" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_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.

585 {
586 .type = ACO_ITEM,
587 .name = "endpoint",
588 .category_match = ACO_BLACKLIST_EXACT,
589 .category = "general",
590 .item_alloc = jingle_endpoint_alloc,
591 .item_find = jingle_endpoint_find,
592 .item_offset = offsetof(struct jingle_config, endpoints),
593};
static void * jingle_endpoint_alloc(const char *cat)
Allocator function for Jingle endpoints.
Definition chan_motif.c:541
@ ACO_ITEM
@ ACO_BLACKLIST_EXACT
static struct ao2_container * endpoints

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

597 {
598 .filename = "motif.conf",
599 .types = ACO_TYPES(&endpoint_option),
600};

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

690 {
691 .type = "Motif",
692 .get_rtp_info = jingle_get_rtp_peer,
693 .get_codec = jingle_get_codec,
694 .update_peer = jingle_set_rtp_peer,
695};
static void jingle_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
Function called by RTP engine to get peer capabilities.
Definition chan_motif.c:679
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.
Definition chan_motif.c:663
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.
Definition chan_motif.c:684

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.

395 {
396 .type = "Motif",
397 .description = "Motif Jingle Channel Driver",
398 .requester = jingle_request,
399 .send_text = jingle_sendtext,
400 .send_digit_begin = jingle_digit_begin,
401 .send_digit_end = jingle_digit_end,
402 .call = jingle_call,
403 .hangup = jingle_hangup,
404 .answer = jingle_answer,
405 .read = jingle_read,
406 .write = jingle_write,
407 .write_video = jingle_write,
408 .exception = jingle_read,
409 .indicate = jingle_indicate,
410 .fixup = jingle_fixup,
412};
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.
static int jingle_answer(struct ast_channel *ast)
Function called by core when we should answer a Jingle session.
static int jingle_digit_begin(struct ast_channel *ast, char digit)
Function called by core to start a DTMF digit.
static int jingle_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Function called by core to stop a DTMF digit.
static int jingle_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Function called by core to change the underlying owner channel.
static int jingle_call(struct ast_channel *ast, const char *dest, int timeout)
Function called by core to actually start calling a remote party.
static struct ast_frame * jingle_read(struct ast_channel *ast)
Function called by core to read any waiting frames.
static int jingle_write(struct ast_channel *ast, struct ast_frame *f)
Function called by core to write frames.
static int jingle_sendtext(struct ast_channel *ast, const char *text)
Function called by core to send text to the remote party of the Jingle session.
static int jingle_hangup(struct ast_channel *ast)
Function called by core to hang up a Jingle session.
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)
Asterisk core interaction functions.
@ AST_CHAN_TP_WANTSJITTER
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Definition channel.h:980
@ AST_CHAN_TP_CREATESJITTER
Channels have this property if they can create jitter; i.e. most VoIP channels.
Definition channel.h:985

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.