Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Functions | Variables
bridge_native_rtp.c File Reference

Native RTP bridging technology module. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/stream.h"
Include dependency graph for bridge_native_rtp.c:

Go to the source code of this file.

Data Structures

struct  native_rtp_bridge_channel_data
 Internal structure which contains instance information about bridged RTP channels. More...
 
struct  native_rtp_framehook_data
 Internal structure which contains bridged RTP channel hook data. More...
 
struct  rtp_glue_data
 
struct  rtp_glue_stream
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 
static int native_rtp_bridge_capable (struct ast_channel *chan)
 
static struct native_rtp_bridge_channel_datanative_rtp_bridge_channel_data_alloc (void)
 
static void native_rtp_bridge_channel_data_free (struct native_rtp_bridge_channel_data *data)
 
static int native_rtp_bridge_compatible (struct ast_bridge *bridge)
 
static int native_rtp_bridge_compatible_check (struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
 
static int native_rtp_bridge_framehook_attach (struct ast_bridge_channel *bridge_channel)
 
static void native_rtp_bridge_framehook_detach (struct ast_bridge_channel *bridge_channel)
 
static int native_rtp_bridge_join (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Forward declarations. More...
 
static void native_rtp_bridge_leave (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static void native_rtp_bridge_start (struct ast_bridge *bridge, struct ast_channel *target)
 
static void native_rtp_bridge_stop (struct ast_bridge *bridge, struct ast_channel *target)
 
static void native_rtp_bridge_suspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static void native_rtp_bridge_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static int native_rtp_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static struct ast_framenative_rtp_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 
static int native_rtp_framehook_consume (void *data, enum ast_frame_type type)
 
static struct ast_stream_topologynative_rtp_request_stream_topology_update (struct ast_stream_topology *existing_topology, struct ast_stream_topology *requested_topology)
 
static void native_rtp_stream_topology_changed (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static void rtp_glue_data_destroy (struct rtp_glue_data *glue)
 
static int rtp_glue_data_get (struct ast_channel *c0, struct rtp_glue_data *glue0, struct ast_channel *c1, struct rtp_glue_data *glue1)
 
static void rtp_glue_data_init (struct rtp_glue_data *glue)
 
static void rtp_glue_data_reset (struct rtp_glue_data *glue)
 
static enum ast_rtp_glue_result rtp_glue_get_current_combined_result (struct ast_channel *c0, struct ast_channel *c1)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Native RTP bridging module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_bridge_technology native_rtp_bridge
 

Detailed Description

Native RTP bridging technology module.

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

Definition in file bridge_native_rtp.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1113 of file bridge_native_rtp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1113 of file bridge_native_rtp.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1113 of file bridge_native_rtp.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 1104 of file bridge_native_rtp.c.

1105{
1107 unload_module();
1109 }
1111}
static struct ast_bridge_technology native_rtp_bridge
static int unload_module(void)
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78

References ast_bridge_technology_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, native_rtp_bridge, and unload_module().

◆ native_rtp_bridge_capable()

static int native_rtp_bridge_capable ( struct ast_channel chan)
static

Definition at line 622 of file bridge_native_rtp.c.

623{
626}
int ast_channel_has_hook_requiring_audio(struct ast_channel *chan)
Check if the channel has any active hooks that require audio.
Definition: channel.c:2524
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42

References ast_channel_has_hook_requiring_audio(), and AST_STATE_UP.

Referenced by native_rtp_bridge_compatible_check().

◆ native_rtp_bridge_channel_data_alloc()

static struct native_rtp_bridge_channel_data * native_rtp_bridge_channel_data_alloc ( void  )
static

Definition at line 150 of file bridge_native_rtp.c.

151{
153
154 data = ast_calloc(1, sizeof(*data));
155 if (data) {
156 rtp_glue_data_init(&data->glue);
157 }
158 return data;
159}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static void rtp_glue_data_init(struct rtp_glue_data *glue)
Internal structure which contains instance information about bridged RTP channels.
struct rtp_glue_data glue
Channel's cached RTP glue information.

References ast_calloc, native_rtp_bridge_channel_data::glue, and rtp_glue_data_init().

Referenced by native_rtp_bridge_join().

◆ native_rtp_bridge_channel_data_free()

static void native_rtp_bridge_channel_data_free ( struct native_rtp_bridge_channel_data data)
static

Definition at line 136 of file bridge_native_rtp.c.

137{
138 ast_debug(2, "Destroying channel tech_pvt data %p\n", data);
139
140 /*
141 * hook_data will probably already have been unreferenced by the framehook detach
142 * and the pointer set to null.
143 */
144 ao2_cleanup(data->hook_data);
145
147 ast_free(data);
148}
#define ast_free(a)
Definition: astmm.h:180
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static void rtp_glue_data_reset(struct rtp_glue_data *glue)
#define ast_debug(level,...)
Log a DEBUG message.
struct native_rtp_framehook_data * hook_data
Channel's hook data.

References ao2_cleanup, ast_debug, ast_free, native_rtp_bridge_channel_data::glue, native_rtp_bridge_channel_data::hook_data, and rtp_glue_data_reset().

Referenced by native_rtp_bridge_join(), and native_rtp_bridge_leave().

◆ native_rtp_bridge_compatible()

static int native_rtp_bridge_compatible ( struct ast_bridge bridge)
static

Definition at line 765 of file bridge_native_rtp.c.

766{
767 struct ast_bridge_channel *bc0;
768 struct ast_bridge_channel *bc1;
769 int is_compatible;
770
771 /* We require two channels before even considering native bridging */
772 if (bridge->num_channels != 2) {
773 ast_debug(1, "Bridge '%s' can not use native RTP bridge as two channels are required\n",
775 return 0;
776 }
777
780
781 ast_channel_lock_both(bc0->chan, bc1->chan);
782 is_compatible = native_rtp_bridge_compatible_check(bridge, bc0, bc1);
785
786 return is_compatible;
787}
static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:429
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
Structure that contains information regarding a channel in a bridge.
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_channel * chan
const ast_string_field uniqueid
Definition: bridge.h:401
struct ast_bridge_channels_list channels
Definition: bridge.h:363
unsigned int num_channels
Definition: bridge.h:373

References ast_channel_lock_both, ast_channel_unlock, ast_debug, AST_LIST_FIRST, AST_LIST_LAST, ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_bridge::channels, native_rtp_bridge_compatible_check(), ast_bridge::num_channels, and ast_bridge::uniqueid.

◆ native_rtp_bridge_compatible_check()

static int native_rtp_bridge_compatible_check ( struct ast_bridge bridge,
struct ast_bridge_channel bc0,
struct ast_bridge_channel bc1 
)
static

Definition at line 632 of file bridge_native_rtp.c.

633{
634 enum ast_rtp_glue_result native_type;
635 int read_ptime0;
636 int read_ptime1;
637 int write_ptime0;
638 int write_ptime1;
639 struct rtp_glue_data glue_a;
640 struct rtp_glue_data glue_b;
641 RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup);
642 RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup);
645
646 ast_debug(1, "Bridge '%s'. Checking compatability for channels '%s' and '%s'\n",
647 bridge->uniqueid, ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
648
649 if (!native_rtp_bridge_capable(bc0->chan)) {
650 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
651 bridge->uniqueid, ast_channel_name(bc0->chan));
652 return 0;
653 }
654
655 if (!native_rtp_bridge_capable(bc1->chan)) {
656 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
657 bridge->uniqueid, ast_channel_name(bc1->chan));
658 return 0;
659 }
660
661 rtp_glue_data_init(&glue_a);
662 glue0 = &glue_a;
663 rtp_glue_data_init(&glue_b);
664 glue1 = &glue_b;
665 if (rtp_glue_data_get(bc0->chan, glue0, bc1->chan, glue1)) {
666 ast_debug(1, "Bridge '%s' can not use native RTP bridge as could not get details\n",
667 bridge->uniqueid);
668 return 0;
669 }
670 native_type = glue0->result;
671
672 if (native_type == AST_RTP_GLUE_RESULT_FORBID) {
673 ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
674 bridge->uniqueid);
675 return 0;
676 }
677
679 && ast_rtp_instance_dtmf_mode_get(glue0->audio.instance)) {
680 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
681 bridge->uniqueid, ast_channel_name(bc0->chan));
682 return 0;
683 }
684
686 && ast_rtp_instance_dtmf_mode_get(glue1->audio.instance)) {
687 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
688 bridge->uniqueid, ast_channel_name(bc1->chan));
689 return 0;
690 }
691
692 if (native_type == AST_RTP_GLUE_RESULT_LOCAL
693 && (ast_rtp_instance_get_engine(glue0->audio.instance)->local_bridge
694 != ast_rtp_instance_get_engine(glue1->audio.instance)->local_bridge
695 || (ast_rtp_instance_get_engine(glue0->audio.instance)->dtmf_compatible
696 && !ast_rtp_instance_get_engine(glue0->audio.instance)->dtmf_compatible(bc0->chan,
697 glue0->audio.instance, bc1->chan, glue1->audio.instance)))) {
698 ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
699 bridge->uniqueid);
700 return 0;
701 }
702
705 if (!cap0 || !cap1) {
706 return 0;
707 }
708
709 /* Make sure that codecs match */
710 if (glue0->cb->get_codec) {
711 glue0->cb->get_codec(bc0->chan, cap0);
712 }
713 if (glue1->cb->get_codec) {
714 glue1->cb->get_codec(bc1->chan, cap1);
715 }
716 if (ast_format_cap_count(cap0) != 0
717 && ast_format_cap_count(cap1) != 0
718 && !ast_format_cap_iscompatible(cap0, cap1)) {
719 struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
720 struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
721
722 ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
723 bridge->uniqueid,
724 ast_format_cap_get_names(cap0, &codec_buf0),
725 ast_format_cap_get_names(cap1, &codec_buf1));
726 return 0;
727 }
728
729 if (glue0->audio.instance && glue1->audio.instance) {
730 unsigned int framing_inst0, framing_inst1;
731 framing_inst0 = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(glue0->audio.instance));
732 framing_inst1 = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(glue1->audio.instance));
733 if (framing_inst0 != framing_inst1) {
734 /* ptimes are asymmetric on the two call legs so we can't use the native bridge */
735 ast_debug(1, "Asymmetric ptimes on the two call legs (%u != %u). Cannot native bridge in RTP\n",
736 framing_inst0, framing_inst1);
737 return 0;
738 }
739 ast_debug(3, "Symmetric ptimes on the two call legs (%u). May be able to native bridge in RTP\n",
740 framing_inst0);
741 }
742
747
748 if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
749 ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
750 bridge->uniqueid,
751 read_ptime0, write_ptime1, read_ptime1, write_ptime0);
752 return 0;
753 }
754 ast_debug(3, "Bridge '%s': Packetization comparison success between RTP streams (read_ptime0:%d == write_ptime1:%d and read_ptime1:%d == write_ptime0:%d).\n",
755 bridge->uniqueid,
756 read_ptime0, write_ptime1, read_ptime1, write_ptime0);
757
758 return 1;
759}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static int native_rtp_bridge_capable(struct ast_channel *chan)
static int rtp_glue_data_get(struct ast_channel *c0, struct rtp_glue_data *glue0, struct ast_channel *c1, struct rtp_glue_data *glue1)
static void rtp_glue_data_destroy(struct rtp_glue_data *glue)
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
struct ast_format * ast_channel_rawwriteformat(struct ast_channel *chan)
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
unsigned int ast_format_cap_get_format_framing(const struct ast_format_cap *cap, const struct ast_format *format)
Get the framing for a format.
Definition: format_cap.c:443
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
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_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if any joint capabilities exist between two capabilities structures.
Definition: format_cap.c:653
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
#define NULL
Definition: resample.c:96
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Definition: rtp_engine.c:2150
ast_rtp_glue_result
Definition: rtp_engine.h:158
@ AST_RTP_GLUE_RESULT_LOCAL
Definition: rtp_engine.h:164
@ AST_RTP_GLUE_RESULT_FORBID
Definition: rtp_engine.h:160
struct ast_rtp_engine * ast_rtp_instance_get_engine(struct ast_rtp_instance *instance)
Get the RTP engine in use on an RTP instance.
Definition: rtp_engine.c:2737
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:748
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1582
#define ast_str_alloca(init_len)
Definition: strings.h:848
struct ast_bridge_features * features
struct ao2_container * dtmf_hooks
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
int(* local_bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
Definition: rtp_engine.h:709
int(* dtmf_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
Definition: rtp_engine.h:717
Support for dynamic strings.
Definition: strings.h:623
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ao2_container_count(), ast_channel_name(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_debug, ast_format_cap_alloc, ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_format_framing(), ast_format_cap_get_names(), ast_format_cap_iscompatible(), AST_FORMAT_CAP_NAMES_LEN, ast_rtp_codecs_get_framing(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, ast_rtp_instance_dtmf_mode_get(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_engine(), ast_str_alloca, ast_bridge_channel::chan, ast_rtp_engine::dtmf_compatible, ast_bridge_features::dtmf_hooks, ast_bridge_channel::features, ast_rtp_engine::local_bridge, native_rtp_bridge_capable(), NULL, RAII_VAR, rtp_glue_data_destroy(), rtp_glue_data_get(), rtp_glue_data_init(), and ast_bridge::uniqueid.

Referenced by native_rtp_bridge_compatible().

◆ native_rtp_bridge_framehook_attach()

static int native_rtp_bridge_framehook_attach ( struct ast_bridge_channel bridge_channel)
static

Definition at line 793 of file bridge_native_rtp.c.

794{
795 struct native_rtp_bridge_channel_data *data = bridge_channel->tech_pvt;
796 struct ast_framehook_interface hook = {
798 .event_cb = native_rtp_framehook,
799 .destroy_cb = __ao2_cleanup,
800 .consume_cb = native_rtp_framehook_consume,
801 .disable_inheritance = 1,
802 };
803
804 ast_assert(data->hook_data == NULL);
805 data->hook_data = ao2_alloc_options(sizeof(*data->hook_data), NULL,
807 if (!data->hook_data) {
808 return -1;
809 }
810
811 ast_debug(2, "Bridge '%s'. Attaching hook data %p to '%s'\n",
812 bridge_channel->bridge->uniqueid, data, ast_channel_name(bridge_channel->chan));
813
814 /* We're giving 1 ref to the framehook and keeping the one from the alloc for ourselves */
815 hook.data = ao2_bump(data->hook_data);
816
817 ast_channel_lock(bridge_channel->chan);
818 data->hook_data->id = ast_framehook_attach(bridge_channel->chan, &hook);
819 ast_channel_unlock(bridge_channel->chan);
820 if (data->hook_data->id < 0) {
821 /*
822 * We need to drop both the reference we hold in data,
823 * and the one the framehook would hold.
824 */
825 ao2_ref(data->hook_data, -2);
826 data->hook_data = NULL;
827
828 return -1;
829 }
830
831 return 0;
832}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
void __ao2_cleanup(void *obj)
Definition: astobj2.c:677
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static struct ast_frame * native_rtp_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
void * tech_pvt
Private information unique to the bridge technology.
#define ast_assert(a)
Definition: utils.h:739

References __ao2_cleanup(), AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, ao2_ref, ast_assert, ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_framehook_interface::data, native_rtp_framehook(), native_rtp_framehook_consume(), NULL, ast_bridge_channel::tech_pvt, ast_bridge::uniqueid, and ast_framehook_interface::version.

Referenced by native_rtp_bridge_join().

◆ native_rtp_bridge_framehook_detach()

static void native_rtp_bridge_framehook_detach ( struct ast_bridge_channel bridge_channel)
static

Definition at line 838 of file bridge_native_rtp.c.

839{
840 struct native_rtp_bridge_channel_data *data = bridge_channel->tech_pvt;
841
842 if (!data || !data->hook_data) {
843 return;
844 }
845
846 ast_debug(2, "Bridge '%s'. Detaching hook data %p from '%s'\n",
847 bridge_channel->bridge->uniqueid, data->hook_data, ast_channel_name(bridge_channel->chan));
848
849 ast_channel_lock(bridge_channel->chan);
850 ast_framehook_detach(bridge_channel->chan, data->hook_data->id);
851 data->hook_data->detached = 1;
852 ast_channel_unlock(bridge_channel->chan);
853 ao2_cleanup(data->hook_data);
854 data->hook_data = NULL;
855}
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
unsigned int detached
Set when this framehook has been detached.
int id
Framehook used to intercept certain control frames.

References ao2_cleanup, ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_framehook_detach(), ast_bridge_channel::bridge, ast_bridge_channel::chan, native_rtp_framehook_data::detached, native_rtp_bridge_channel_data::hook_data, native_rtp_framehook_data::id, NULL, ast_bridge_channel::tech_pvt, and ast_bridge::uniqueid.

Referenced by native_rtp_bridge_leave().

◆ native_rtp_bridge_join()

static int native_rtp_bridge_join ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

Forward declarations.

Definition at line 967 of file bridge_native_rtp.c.

968{
969 struct ast_stream_topology *req_top;
970 struct ast_stream_topology *existing_top;
971 struct ast_stream_topology *new_top;
972 struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
973 struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
974
975 ast_debug(2, "Bridge '%s'. Channel '%s' is joining bridge tech\n",
977
979
981 /* The channel will rejoin when it is unsuspended */
982 return 0;
983 }
984
986 if (!bridge_channel->tech_pvt) {
987 return -1;
988 }
989
993 return -1;
994 }
995
996 if (c0 != c1) {
997 /* When both channels are joined we want to try to improve the experience by
998 * raising the number of streams so they match.
999 */
1000 ast_channel_lock_both(c0, c1);
1001 req_top = ast_channel_get_stream_topology(c0);
1002 existing_top = ast_channel_get_stream_topology(c1);
1003 if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
1004 SWAP(req_top, existing_top);
1005 SWAP(c0, c1);
1006 }
1007 new_top = native_rtp_request_stream_topology_update(existing_top, req_top);
1010
1011 if (new_top) {
1013 ast_stream_topology_free(new_top);
1014 }
1015 }
1016
1018 return 0;
1019}
static struct ast_stream_topology * native_rtp_request_stream_topology_update(struct ast_stream_topology *existing_topology, struct ast_stream_topology *requested_topology)
static struct native_rtp_bridge_channel_data * native_rtp_bridge_channel_data_alloc(void)
static void native_rtp_bridge_channel_data_free(struct native_rtp_bridge_channel_data *data)
static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channel *target)
int ast_channel_request_stream_topology_change(struct ast_channel *chan, struct ast_stream_topology *topology, void *change_source)
Request that the stream topology of a channel change.
Definition: channel.c:10966
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
unsigned int suspended
Main Channel structure associated with a channel.
struct ast_bridge_channel * bridge_channel
struct ast_bridge * bridge
#define SWAP(a, b)
Definition: utils.h:235

References ast_assert, ast_channel_get_stream_topology(), ast_channel_lock_both, ast_channel_name(), ast_channel_request_stream_topology_change(), ast_channel_unlock, ast_debug, AST_LIST_FIRST, AST_LIST_LAST, ast_stream_topology_free(), ast_stream_topology_get_count(), ast_channel::bridge, ast_channel::bridge_channel, ast_bridge_channel::chan, ast_bridge::channels, native_rtp_bridge, native_rtp_bridge_channel_data_alloc(), native_rtp_bridge_channel_data_free(), native_rtp_bridge_framehook_attach(), native_rtp_bridge_start(), native_rtp_request_stream_topology_update(), NULL, ast_bridge_channel::suspended, SWAP, ast_bridge_channel::tech_pvt, and ast_bridge::uniqueid.

Referenced by native_rtp_bridge_unsuspend().

◆ native_rtp_bridge_leave()

static void native_rtp_bridge_leave ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 1036 of file bridge_native_rtp.c.

1037{
1038 ast_debug(2, "Bridge '%s'. Channel '%s' is leaving bridge tech\n",
1039 bridge->uniqueid, ast_channel_name(bridge_channel->chan));
1040
1041 if (!bridge_channel->tech_pvt) {
1042 return;
1043 }
1044
1045 native_rtp_bridge_framehook_detach(bridge_channel);
1047
1049 bridge_channel->tech_pvt = NULL;
1050}
static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)

References ast_channel_name(), ast_debug, ast_channel::bridge, ast_channel::bridge_channel, ast_bridge_channel::chan, native_rtp_bridge_channel_data_free(), native_rtp_bridge_framehook_detach(), native_rtp_bridge_stop(), NULL, ast_bridge_channel::tech_pvt, and ast_bridge::uniqueid.

Referenced by native_rtp_bridge_suspend().

◆ native_rtp_bridge_start()

static void native_rtp_bridge_start ( struct ast_bridge bridge,
struct ast_channel target 
)
static

Definition at line 289 of file bridge_native_rtp.c.

290{
293 struct native_rtp_bridge_channel_data *data0;
294 struct native_rtp_bridge_channel_data *data1;
295 struct rtp_glue_data *glue0;
296 struct rtp_glue_data *glue1;
297 struct ast_format_cap *cap0;
298 struct ast_format_cap *cap1;
299 enum ast_rtp_glue_result native_type;
300
301 if (bc0 == bc1) {
302 return;
303 }
304 data0 = bc0->tech_pvt;
305 data1 = bc1->tech_pvt;
306 if (!data0 || !data1) {
307 /* Not all channels are joined with the bridge tech yet */
308 return;
309 }
310 glue0 = &data0->glue;
311 glue1 = &data1->glue;
312
313 ast_channel_lock_both(bc0->chan, bc1->chan);
314
315 if (!glue0->cb || !glue1->cb) {
316 /*
317 * Somebody doesn't have glue data so the bridge isn't running
318 *
319 * Actually neither side should have glue data.
320 */
321 ast_assert(!glue0->cb && !glue1->cb);
322
323 if (rtp_glue_data_get(bc0->chan, glue0, bc1->chan, glue1)) {
324 /*
325 * This might happen if one of the channels got masqueraded
326 * at a critical time. It's a bit of a stretch even then
327 * since the channel is in a bridge.
328 */
329 goto done;
330 }
331 }
332
333 ast_debug(2, "Bridge '%s'. Tech starting '%s' and '%s' with target '%s'\n",
334 bridge->uniqueid, ast_channel_name(bc0->chan), ast_channel_name(bc1->chan),
335 target ? ast_channel_name(target) : "none");
336
337 native_type = glue0->result;
338
339 switch (native_type) {
343 }
346 }
349 ast_verb(4, "Locally RTP bridged '%s' and '%s' in stack\n",
351 break;
355 if (!cap0 || !cap1) {
356 ao2_cleanup(cap0);
357 ao2_cleanup(cap1);
358 break;
359 }
360
361 if (glue0->cb->get_codec) {
362 glue0->cb->get_codec(bc0->chan, cap0);
363 }
364 if (glue1->cb->get_codec) {
365 glue1->cb->get_codec(bc1->chan, cap1);
366 }
367
368 /*
369 * If we have a target, it's the channel that received the UNHOLD or
370 * UPDATE_RTP_PEER frame and was told to resume
371 */
372 if (!target) {
373 /* Send both channels to remote */
374 data0->remote_cb = glue0->cb;
375 data1->remote_cb = glue1->cb;
376 glue0->cb->update_peer(bc0->chan, glue1->audio.instance, glue1->video.instance, NULL, cap1, 0);
377 glue1->cb->update_peer(bc1->chan, glue0->audio.instance, glue0->video.instance, NULL, cap0, 0);
378 ast_verb(4, "Remotely bridged '%s' and '%s' - media will flow directly between them\n",
380 } else {
381 /*
382 * If a target was provided, it is the recipient of an unhold or an update and needs to have
383 * its media redirected to fit the current remote bridging needs. The other channel is either
384 * already set up to handle the new media path or will have its own set of updates independent
385 * of this pass.
386 */
387 ast_debug(2, "Bridge '%s'. Sending '%s' back to remote\n",
388 bridge->uniqueid, ast_channel_name(target));
389 if (bc0->chan == target) {
390 data0->remote_cb = glue0->cb;
391 glue0->cb->update_peer(bc0->chan, glue1->audio.instance, glue1->video.instance, NULL, cap1, 0);
392 } else {
393 data1->remote_cb = glue1->cb;
394 glue1->cb->update_peer(bc1->chan, glue0->audio.instance, glue0->video.instance, NULL, cap0, 0);
395 }
396 }
397
398 ao2_cleanup(cap0);
399 ao2_cleanup(cap1);
400 break;
402 break;
403 }
404
405 if (native_type != AST_RTP_GLUE_RESULT_REMOTE) {
406 /* Bring any remaining channels back to us. */
407 if (data0->remote_cb) {
408 ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
409 bridge->uniqueid, ast_channel_name(bc0->chan));
410 data0->remote_cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
411 data0->remote_cb = NULL;
412 }
413 if (data1->remote_cb) {
414 ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
415 bridge->uniqueid, ast_channel_name(bc1->chan));
416 data1->remote_cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
417 data1->remote_cb = NULL;
418 }
419 }
420
421done:
424}
#define ast_verb(level,...)
@ AST_RTP_GLUE_RESULT_REMOTE
Definition: rtp_engine.h:162
void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_rtp_instance *bridged)
Set the other RTP instance that an instance is bridged to.
Definition: rtp_engine.c:2257
void(* get_codec)(struct ast_channel *chan, struct ast_format_cap *result_cap)
Callback for retrieving codecs that the channel can do. Result returned in result_cap.
Definition: rtp_engine.h:807
int(* update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active)
Definition: rtp_engine.h:802
struct ast_rtp_glue * remote_cb
Glue callbacks to bring remote channel streams back to Asterisk.
struct rtp_glue_stream audio
struct rtp_glue_stream video
enum ast_rtp_glue_result result
struct ast_rtp_glue * cb
glue callbacks
struct ast_rtp_instance * instance
RTP instance.
int done
Definition: test_amihooks.c:48

References ao2_cleanup, ast_assert, ast_channel_lock_both, ast_channel_name(), ast_channel_unlock, ast_debug, ast_format_cap_alloc, AST_FORMAT_CAP_FLAG_DEFAULT, AST_LIST_FIRST, AST_LIST_LAST, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, ast_rtp_instance_get_engine(), ast_rtp_instance_set_bridged(), ast_verb, rtp_glue_data::audio, ast_bridge_channel::bridge, rtp_glue_data::cb, ast_bridge_channel::chan, ast_bridge::channels, done, ast_rtp_glue::get_codec, native_rtp_bridge_channel_data::glue, rtp_glue_stream::instance, ast_rtp_engine::local_bridge, NULL, native_rtp_bridge_channel_data::remote_cb, rtp_glue_data::result, rtp_glue_data_get(), ast_bridge_channel::tech_pvt, ast_bridge::uniqueid, ast_rtp_glue::update_peer, and rtp_glue_data::video.

Referenced by native_rtp_bridge_join(), and native_rtp_framehook().

◆ native_rtp_bridge_stop()

static void native_rtp_bridge_stop ( struct ast_bridge bridge,
struct ast_channel target 
)
static

Definition at line 435 of file bridge_native_rtp.c.

436{
439 struct native_rtp_bridge_channel_data *data0;
440 struct native_rtp_bridge_channel_data *data1;
441 struct rtp_glue_data *glue0;
442 struct rtp_glue_data *glue1;
443
444 if (bc0 == bc1) {
445 return;
446 }
447 data0 = bc0->tech_pvt;
448 data1 = bc1->tech_pvt;
449 if (!data0 || !data1) {
450 /* Not all channels are joined with the bridge tech */
451 return;
452 }
453 glue0 = &data0->glue;
454 glue1 = &data1->glue;
455
456 ast_debug(2, "Bridge '%s'. Tech stopping '%s' and '%s' with target '%s'\n",
457 bridge->uniqueid, ast_channel_name(bc0->chan), ast_channel_name(bc1->chan),
458 target ? ast_channel_name(target) : "none");
459
460 if (!glue0->cb || !glue1->cb) {
461 /*
462 * Somebody doesn't have glue data so the bridge isn't running
463 *
464 * Actually neither side should have glue data.
465 */
466 ast_assert(!glue0->cb && !glue1->cb);
467 /* At most one channel can be left at the remote endpoint here. */
468 ast_assert(!data0->remote_cb || !data1->remote_cb);
469
470 /* Bring selected channel streams back to us */
471 if (data0->remote_cb && (!target || target == bc0->chan)) {
473 ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
474 bridge->uniqueid, ast_channel_name(bc0->chan));
475 data0->remote_cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
476 data0->remote_cb = NULL;
478 }
479 if (data1->remote_cb && (!target || target == bc1->chan)) {
481 ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
482 bridge->uniqueid, ast_channel_name(bc1->chan));
483 data1->remote_cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
484 data1->remote_cb = NULL;
486 }
487 return;
488 }
489
490 ast_channel_lock_both(bc0->chan, bc1->chan);
491
492 switch (glue0->result) {
496 }
499 }
502 break;
504 if (target) {
505 /*
506 * If a target was provided, it is being put on hold and should expect to
507 * receive media from Asterisk instead of what it was previously connected to.
508 */
509 ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
510 bridge->uniqueid, ast_channel_name(target));
511 if (bc0->chan == target) {
512 data0->remote_cb = NULL;
513 glue0->cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
514 } else {
515 data1->remote_cb = NULL;
516 glue1->cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
517 }
518 } else {
519 data0->remote_cb = NULL;
520 data1->remote_cb = NULL;
521 /*
522 * XXX We don't want to bring back the channels if we are
523 * switching to T.38. We have received a reinvite on one channel
524 * and we will be sending a reinvite on the other to start T.38.
525 * If we bring the streams back now we confuse the chan_pjsip
526 * channel driver processing the incoming T.38 reinvite with
527 * reinvite glare. I think this is really a bug in chan_pjsip
528 * that this exception case is working around.
529 */
532 ast_debug(2, "Bridge '%s'. Bringing back '%s' and '%s' to us\n",
533 bridge->uniqueid, ast_channel_name(bc0->chan),
534 ast_channel_name(bc1->chan));
535 glue0->cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
536 glue1->cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
537 } else {
538 ast_debug(2, "Bridge '%s'. Skip bringing back '%s' and '%s' to us\n",
539 bridge->uniqueid, ast_channel_name(bc0->chan),
540 ast_channel_name(bc1->chan));
541 }
542 }
543 break;
545 break;
546 }
547
548 rtp_glue_data_reset(glue0);
549 rtp_glue_data_reset(glue1);
550
551 ast_debug(2, "Discontinued RTP bridging of '%s' and '%s' - media will flow through Asterisk core\n",
553
556}
static enum ast_rtp_glue_result rtp_glue_get_current_combined_result(struct ast_channel *c0, struct ast_channel *c1)

References ast_assert, ast_channel_lock, ast_channel_lock_both, ast_channel_name(), ast_channel_unlock, ast_debug, AST_LIST_FIRST, AST_LIST_LAST, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, ast_rtp_instance_get_engine(), ast_rtp_instance_set_bridged(), rtp_glue_data::audio, ast_bridge_channel::bridge, rtp_glue_data::cb, ast_bridge_channel::chan, ast_bridge::channels, native_rtp_bridge_channel_data::glue, rtp_glue_stream::instance, ast_rtp_engine::local_bridge, NULL, native_rtp_bridge_channel_data::remote_cb, rtp_glue_data::result, rtp_glue_data_reset(), rtp_glue_get_current_combined_result(), ast_bridge_channel::tech_pvt, ast_bridge::uniqueid, and ast_rtp_glue::update_peer.

Referenced by native_rtp_bridge_leave(), and native_rtp_framehook().

◆ native_rtp_bridge_suspend()

static void native_rtp_bridge_suspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 1056 of file bridge_native_rtp.c.

1057{
1058 ast_debug(2, "Bridge '%s'. Channel '%s' is suspending from bridge tech\n",
1059 bridge->uniqueid, ast_channel_name(bridge_channel->chan));
1060 native_rtp_bridge_leave(bridge, bridge_channel);
1061}
static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)

References ast_channel_name(), ast_debug, ast_channel::bridge, ast_channel::bridge_channel, ast_bridge_channel::chan, native_rtp_bridge_leave(), and ast_bridge::uniqueid.

◆ native_rtp_bridge_unsuspend()

static void native_rtp_bridge_unsuspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 1025 of file bridge_native_rtp.c.

1026{
1027 ast_debug(2, "Bridge '%s'. Channel '%s' is unsuspended back to bridge tech\n",
1028 bridge->uniqueid, ast_channel_name(bridge_channel->chan));
1029 native_rtp_bridge_join(bridge, bridge_channel);
1030}
static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Forward declarations.

References ast_channel_name(), ast_debug, ast_channel::bridge, ast_channel::bridge_channel, ast_bridge_channel::chan, native_rtp_bridge_join(), and ast_bridge::uniqueid.

◆ native_rtp_bridge_write()

static int native_rtp_bridge_write ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
)
static

Definition at line 1063 of file bridge_native_rtp.c.

1064{
1065 const struct ast_control_t38_parameters *t38_parameters;
1066 int defer = 0;
1067
1068 if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
1069 /* This frame was successfully queued so no need to defer */
1070 return 0;
1071 }
1072
1073 /* Depending on the frame defer it so when the next channel joins it receives it */
1074 switch (frame->frametype) {
1075 case AST_FRAME_CONTROL:
1076 switch (frame->subclass.integer) {
1078 t38_parameters = frame->data.ptr;
1079 switch (t38_parameters->request_response) {
1081 defer = -1;
1082 break;
1083 default:
1084 break;
1085 }
1086 break;
1087 default:
1088 break;
1089 }
1090 break;
1091 default:
1092 break;
1093 }
1094
1095 return defer;
1096}
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Queue the given frame to everyone else.
@ AST_T38_REQUEST_NEGOTIATE
@ AST_FRAME_CONTROL
@ AST_CONTROL_T38_PARAMETERS
enum ast_control_t38 request_response
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype

References ast_bridge_queue_everyone_else(), AST_CONTROL_T38_PARAMETERS, AST_FRAME_CONTROL, AST_T38_REQUEST_NEGOTIATE, ast_frame::data, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.

◆ native_rtp_framehook()

static struct ast_frame * native_rtp_framehook ( struct ast_channel chan,
struct ast_frame f,
enum ast_framehook_event  event,
void *  data 
)
static

Definition at line 562 of file bridge_native_rtp.c.

564{
565 struct ast_bridge *bridge;
566 struct native_rtp_framehook_data *native_data = data;
567
568 if (!f
571 return f;
572 }
573
574 bridge = ast_channel_get_bridge(chan);
575 if (bridge) {
576 /* native_rtp_bridge_start/stop are not being called from bridging
577 core so we need to lock the bridge prior to calling these functions
578 Unfortunately that means unlocking the channel, but as it
579 should not be modified this should be okay... hopefully...
580 unless this channel is being moved around right now and is in
581 the process of having this framehook removed (which is fine). To
582 ensure we then don't stop or start when we shouldn't we consult
583 the data provided. If this framehook has been detached then the
584 detached variable will be set. This is safe to check as it is only
585 manipulated with the bridge lock held. */
586 ast_channel_unlock(chan);
587 ast_bridge_lock(bridge);
588 if (!native_data->detached) {
589 switch (f->subclass.integer) {
590 case AST_CONTROL_HOLD:
591 native_rtp_bridge_stop(bridge, chan);
592 break;
595 native_rtp_bridge_start(bridge, chan);
596 break;
597 default:
598 break;
599 }
600 }
601 ast_bridge_unlock(bridge);
602 ao2_ref(bridge, -1);
603 ast_channel_lock(chan);
604 }
605
606 return f;
607}
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:470
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10534
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_HOLD
@ AST_CONTROL_UPDATE_RTP_PEER
Structure that contains information about a bridge.
Definition: bridge.h:349
Definition: astman.c:222
Internal structure which contains bridged RTP channel hook data.

References ao2_ref, ast_bridge_lock, ast_bridge_unlock, ast_channel_get_bridge(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_FRAME_CONTROL, AST_FRAMEHOOK_EVENT_WRITE, native_rtp_framehook_data::detached, ast_frame::frametype, ast_frame_subclass::integer, native_rtp_bridge_start(), native_rtp_bridge_stop(), and ast_frame::subclass.

Referenced by native_rtp_bridge_framehook_attach().

◆ native_rtp_framehook_consume()

static int native_rtp_framehook_consume ( void *  data,
enum ast_frame_type  type 
)
static

Definition at line 613 of file bridge_native_rtp.c.

614{
615 return (type == AST_FRAME_CONTROL ? 1 : 0);
616}
static const char type[]
Definition: chan_ooh323.c:109

References AST_FRAME_CONTROL, and type.

Referenced by native_rtp_bridge_framehook_attach().

◆ native_rtp_request_stream_topology_update()

static struct ast_stream_topology * native_rtp_request_stream_topology_update ( struct ast_stream_topology existing_topology,
struct ast_stream_topology requested_topology 
)
static

Definition at line 857 of file bridge_native_rtp.c.

860{
861 struct ast_stream *stream;
862 const struct ast_format_cap *audio_formats = NULL;
863 struct ast_stream_topology *new_topology;
864 int i;
865
866 new_topology = ast_stream_topology_clone(requested_topology);
867 if (!new_topology) {
868 return NULL;
869 }
870
871 /* We find an existing stream with negotiated audio formats that we can place into
872 * any audio streams in the new topology to ensure that negotiation succeeds. Some
873 * endpoints incorrectly terminate the call if SDP negotiation fails.
874 */
875 for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
876 stream = ast_stream_topology_get_stream(existing_topology, i);
877
880 continue;
881 }
882
883 audio_formats = ast_stream_get_formats(stream);
884 break;
885 }
886
887 if (audio_formats) {
888 for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
889 stream = ast_stream_topology_get_stream(new_topology, i);
890
893 continue;
894 }
895
896 /* We haven't actually modified audio_formats so this is safe */
897 ast_stream_set_formats(stream, (struct ast_format_cap *)audio_formats);
898 }
899 }
900
901 for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
902 stream = ast_stream_topology_get_stream(new_topology, i);
903
904 /* For both recvonly and sendonly the stream state reflects our state, that is we
905 * are receiving only and we are sending only. Since we are renegotiating a remote
906 * party we need to swap this to reflect what we will be doing. That is, if we are
907 * receiving from Alice then we want to be sending to Bob, so swap recvonly to
908 * sendonly.
909 */
912 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
914 }
915 }
916
917 return new_topology;
918}
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_STREAM_STATE_RECVONLY
Set when the stream is receiving media only.
Definition: stream.h:90
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
@ AST_STREAM_STATE_SENDONLY
Set when the stream is sending media only.
Definition: stream.h:86
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667

References AST_MEDIA_TYPE_AUDIO, ast_stream_get_formats(), ast_stream_get_state(), ast_stream_get_type(), ast_stream_set_formats(), ast_stream_set_state(), AST_STREAM_STATE_RECVONLY, AST_STREAM_STATE_REMOVED, AST_STREAM_STATE_SENDONLY, ast_stream_topology_clone(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), and NULL.

Referenced by native_rtp_bridge_join(), and native_rtp_stream_topology_changed().

◆ native_rtp_stream_topology_changed()

static void native_rtp_stream_topology_changed ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 920 of file bridge_native_rtp.c.

922{
923 struct ast_channel *c0 = bridge_channel->chan;
924 struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
925 struct ast_stream_topology *req_top;
926 struct ast_stream_topology *existing_top;
927 struct ast_stream_topology *new_top;
928
929 ast_bridge_channel_stream_map(bridge_channel);
930
932 == &native_rtp_bridge) {
933 return;
934 }
935
936 if (c0 == c1) {
937 c1 = AST_LIST_LAST(&bridge->channels)->chan;
938 }
939
940 if (c0 == c1) {
941 return;
942 }
943
944 /* If a party renegotiates we want to renegotiate their counterpart to a matching
945 * topology.
946 */
947 ast_channel_lock_both(c0, c1);
949 existing_top = ast_channel_get_stream_topology(c1);
950 new_top = native_rtp_request_stream_topology_update(existing_top, req_top);
953
954 if (!new_top) {
955 /* Failure. We'll just have to live with the current topology. */
956 return;
957 }
958
961}
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel's stream topology to and from the bridge.
void * ast_channel_get_stream_topology_change_source(struct ast_channel *chan)
Retrieve the source that initiated the last stream topology change.

References ast_bridge_channel_stream_map(), ast_channel_get_stream_topology(), ast_channel_get_stream_topology_change_source(), ast_channel_lock_both, ast_channel_request_stream_topology_change(), ast_channel_unlock, AST_LIST_FIRST, AST_LIST_LAST, ast_stream_topology_free(), ast_channel::bridge, ast_channel::bridge_channel, ast_bridge_channel::chan, ast_bridge::channels, native_rtp_bridge, and native_rtp_request_stream_topology_update().

◆ rtp_glue_data_destroy()

static void rtp_glue_data_destroy ( struct rtp_glue_data glue)
static

◆ rtp_glue_data_get()

static int rtp_glue_data_get ( struct ast_channel c0,
struct rtp_glue_data glue0,
struct ast_channel c1,
struct rtp_glue_data glue1 
)
static

Definition at line 168 of file bridge_native_rtp.c.

170{
171 struct ast_rtp_glue *cb0;
172 struct ast_rtp_glue *cb1;
173 enum ast_rtp_glue_result combined_result;
174
177 if (!cb0 || !cb1) {
178 /* One or both channels doesn't have any RTP glue registered. */
179 return -1;
180 }
181
182 /* The glue callbacks bump the RTP instance refcounts for us. */
183
184 glue0->cb = cb0;
185 glue0->audio.result = cb0->get_rtp_info(c0, &glue0->audio.instance);
186 glue0->video.result = cb0->get_vrtp_info
188
189 glue1->cb = cb1;
190 glue1->audio.result = cb1->get_rtp_info(c1, &glue1->audio.instance);
191 glue1->video.result = cb1->get_vrtp_info
193
194 /*
195 * Now determine the combined glue result.
196 */
197
198 /* Apply any limitations on direct media bridging that may be present */
199 if (glue0->audio.result == glue1->audio.result && glue1->audio.result == AST_RTP_GLUE_RESULT_REMOTE) {
200 if (glue0->cb->allow_rtp_remote && !glue0->cb->allow_rtp_remote(c0, glue1->audio.instance)) {
201 /* If the allow_rtp_remote indicates that remote isn't allowed, revert to local bridge */
203 } else if (glue1->cb->allow_rtp_remote && !glue1->cb->allow_rtp_remote(c1, glue0->audio.instance)) {
205 }
206 }
207 if (glue0->video.result == glue1->video.result && glue1->video.result == AST_RTP_GLUE_RESULT_REMOTE) {
208 if (glue0->cb->allow_vrtp_remote && !glue0->cb->allow_vrtp_remote(c0, glue1->video.instance)) {
209 /* If the allow_vrtp_remote indicates that remote isn't allowed, revert to local bridge */
211 } else if (glue1->cb->allow_vrtp_remote && !glue1->cb->allow_vrtp_remote(c1, glue0->video.instance)) {
213 }
214 }
215
216 /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
221 }
226 }
227
228 /* The order of preference is: forbid, local, and remote. */
231 /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
232 combined_result = AST_RTP_GLUE_RESULT_FORBID;
233 } else if (glue0->audio.result == AST_RTP_GLUE_RESULT_LOCAL
235 combined_result = AST_RTP_GLUE_RESULT_LOCAL;
236 } else {
237 combined_result = AST_RTP_GLUE_RESULT_REMOTE;
238 }
239 glue0->result = combined_result;
240 glue1->result = combined_result;
241
242 return 0;
243}
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_rtp_glue * ast_rtp_instance_get_glue(const char *type)
Get the RTP glue that binds a channel to the RTP engine.
Definition: rtp_engine.c:2219
int(* allow_vrtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance)
Used to prevent two channels from remotely bridging video rtp if the channel tech has a reason for pr...
Definition: rtp_engine.h:793
enum ast_rtp_glue_result(* get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying audio.
Definition: rtp_engine.h:775
int(* allow_rtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance)
Used to prevent two channels from remotely bridging audio rtp if the channel tech has a reason for pr...
Definition: rtp_engine.h:781
enum ast_rtp_glue_result(* get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying video.
Definition: rtp_engine.h:787
enum ast_rtp_glue_result result
glue result

References ast_rtp_glue::allow_rtp_remote, ast_rtp_glue::allow_vrtp_remote, ast_channel_tech(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, ast_rtp_instance_get_glue(), rtp_glue_data::audio, rtp_glue_data::cb, ast_rtp_glue::get_rtp_info, ast_rtp_glue::get_vrtp_info, rtp_glue_stream::instance, rtp_glue_stream::result, rtp_glue_data::result, type, and rtp_glue_data::video.

Referenced by native_rtp_bridge_compatible_check(), native_rtp_bridge_start(), and rtp_glue_get_current_combined_result().

◆ rtp_glue_data_init()

static void rtp_glue_data_init ( struct rtp_glue_data glue)
static

◆ rtp_glue_data_reset()

static void rtp_glue_data_reset ( struct rtp_glue_data glue)
static

◆ rtp_glue_get_current_combined_result()

static enum ast_rtp_glue_result rtp_glue_get_current_combined_result ( struct ast_channel c0,
struct ast_channel c1 
)
static

Definition at line 257 of file bridge_native_rtp.c.

259{
260 struct rtp_glue_data glue_a;
261 struct rtp_glue_data glue_b;
262 struct rtp_glue_data *glue0;
263 struct rtp_glue_data *glue1;
264 enum ast_rtp_glue_result combined_result;
265
266 rtp_glue_data_init(&glue_a);
267 glue0 = &glue_a;
268 rtp_glue_data_init(&glue_b);
269 glue1 = &glue_b;
270 if (rtp_glue_data_get(c0, glue0, c1, glue1)) {
272 }
273
274 combined_result = glue0->result;
277 return combined_result;
278}

References AST_RTP_GLUE_RESULT_FORBID, rtp_glue_data::result, rtp_glue_data_destroy(), rtp_glue_data_get(), and rtp_glue_data_init().

Referenced by native_rtp_bridge_stop().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1098 of file bridge_native_rtp.c.

1099{
1101 return 0;
1102}
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:263

References ast_bridge_technology_unregister(), and native_rtp_bridge.

Referenced by load_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Native RTP bridging module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 1113 of file bridge_native_rtp.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1113 of file bridge_native_rtp.c.

◆ native_rtp_bridge

struct ast_bridge_technology native_rtp_bridge
static