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

Simple two channel bridging 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/stream.h"
Include dependency graph for bridge_simple.c:

Go to the source code of this file.

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 simple_bridge_join (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static struct ast_stream_topologysimple_bridge_request_stream_topology_update (struct ast_stream_topology *existing_topology, struct ast_stream_topology *requested_topology)
 
static void simple_bridge_stream_topology_changed (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 
static int simple_bridge_write (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Simple two channel 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 simple_bridge
 

Detailed Description

Simple two channel bridging module.

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

Definition in file bridge_simple.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 290 of file bridge_simple.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 290 of file bridge_simple.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 290 of file bridge_simple.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 281 of file bridge_simple.c.

282{
286 }
288}
static int unload_module(void)
static struct ast_bridge_technology simple_bridge
Definition: bridge_simple.c:52
#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, simple_bridge, and unload_module().

◆ simple_bridge_join()

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

Definition at line 124 of file bridge_simple.c.

125{
126 struct ast_stream_topology *req_top;
127 struct ast_stream_topology *existing_top;
128 struct ast_stream_topology *new_top;
129 struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
130 struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
131 int unhold_c0, unhold_c1;
132
133 /*
134 * If this is the first channel we can't make it compatible...
135 * unless we make it compatible with itself. O.o
136 */
137 if (c0 == c1) {
138 return 0;
139 }
140
141 if (ast_channel_make_compatible(c0, c1)) {
142 return -1;
143 }
144
145 /* When both channels are joined we want to try to improve the experience by
146 * raising the number of streams so they match.
147 */
148 ast_channel_lock_both(c0, c1);
150 existing_top = ast_channel_get_stream_topology(c1);
152 SWAP(req_top, existing_top);
153 SWAP(c0, c1);
154 }
155 new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
156
157 /* The ast_channel_hold_state() and ast_channel_name() accessors need to be
158 * called with the associated channel lock held.
159 */
160 if ((unhold_c1 = ast_channel_hold_state(c1) == AST_CONTROL_HOLD)) {
161 ast_debug(1, "Channel %s simulating UNHOLD for bridge simple join.\n", ast_channel_name(c1));
162 }
163
164 if ((unhold_c0 = ast_channel_hold_state(c0) == AST_CONTROL_HOLD)) {
165 ast_debug(1, "Channel %s simulating UNHOLD for bridge simple join.\n", ast_channel_name(c0));
166 }
167
170
171 if (unhold_c1) {
173 }
174
175 if (unhold_c0) {
177 }
178
179 if (!new_top) {
180 /* Failure. We'll just have to live with the current topology. */
181 return 0;
182 }
183
184 if (!ast_stream_topology_equal(new_top, existing_top)) {
186 } else {
187 ast_debug(3, "%s: Topologies already match. Current: %s Requested: %s\n",
189 ast_str_tmp(256, ast_stream_topology_to_str(existing_top, &STR_TMP)),
190 ast_str_tmp(256, ast_stream_topology_to_str(new_top, &STR_TMP)));
191 }
193
194 return 0;
195}
static struct ast_stream_topology * simple_bridge_request_stream_topology_update(struct ast_stream_topology *existing_topology, struct ast_stream_topology *requested_topology)
Definition: bridge_simple.c:61
const char * ast_channel_name(const struct ast_channel *chan)
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
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6720
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
int ast_channel_hold_state(const struct ast_channel *chan)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
#define ast_channel_unlock(chan)
Definition: channel.h:2923
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_HOLD
#define ast_debug(level,...)
Log a DEBUG message.
#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
const char * ast_stream_topology_to_str(const struct ast_stream_topology *topology, struct ast_str **buf)
Get a string representing the topology for debugging/display purposes.
Definition: stream.c:936
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
int ast_stream_topology_equal(const struct ast_stream_topology *left, const struct ast_stream_topology *right)
Compare two stream topologies to see if they are equal.
Definition: stream.c:696
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
Definition: strings.h:1189
struct ast_bridge_channels_list channels
Definition: bridge.h:363
Main Channel structure associated with a channel.
struct ast_bridge * bridge
#define SWAP(a, b)
Definition: utils.h:235

References ast_channel_get_stream_topology(), ast_channel_hold_state(), ast_channel_lock_both, ast_channel_make_compatible(), ast_channel_name(), ast_channel_request_stream_topology_change(), ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), AST_LIST_FIRST, AST_LIST_LAST, ast_str_tmp, ast_stream_topology_equal(), ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_to_str(), ast_channel::bridge, ast_bridge::channels, simple_bridge, simple_bridge_request_stream_topology_update(), and SWAP.

◆ simple_bridge_request_stream_topology_update()

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

Definition at line 61 of file bridge_simple.c.

64{
65 struct ast_stream *stream;
66 const struct ast_format_cap *audio_formats = NULL;
67 struct ast_stream_topology *new_topology;
68 int i;
69
70 new_topology = ast_stream_topology_clone(requested_topology);
71 if (!new_topology) {
72 return NULL;
73 }
74
75 /* We find an existing stream with negotiated audio formats that we can place into
76 * any audio streams in the new topology to ensure that negotiation succeeds. Some
77 * endpoints incorrectly terminate the call if SDP negotiation fails.
78 */
79 for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
80 stream = ast_stream_topology_get_stream(existing_topology, i);
81
84 continue;
85 }
86
87 audio_formats = ast_stream_get_formats(stream);
88 break;
89 }
90
91 if (audio_formats) {
92 for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
93 stream = ast_stream_topology_get_stream(new_topology, i);
94
97 continue;
98 }
99
100 /* We haven't actually modified audio_formats so this is safe */
101 ast_stream_set_formats(stream, (struct ast_format_cap *)audio_formats);
102 }
103 }
104
105 for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
106 stream = ast_stream_topology_get_stream(new_topology, i);
107
108 /* For both recvonly and sendonly the stream state reflects our state, that is we
109 * are receiving only and we are sending only. Since we are renegotiating a remote
110 * party we need to swap this to reflect what we will be doing. That is, if we are
111 * receiving from Alice then we want to be sending to Bob, so swap recvonly to
112 * sendonly.
113 */
116 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
118 }
119 }
120
121 return new_topology;
122}
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
#define NULL
Definition: resample.c:96
@ 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
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54

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 simple_bridge_join(), and simple_bridge_stream_topology_changed().

◆ simple_bridge_stream_topology_changed()

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

Definition at line 232 of file bridge_simple.c.

234{
235 struct ast_channel *c0 = bridge_channel->chan;
236 struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
237 struct ast_stream_topology *req_top;
238 struct ast_stream_topology *existing_top;
239 struct ast_stream_topology *new_top;
240
241 ast_bridge_channel_stream_map(bridge_channel);
242
244 == &simple_bridge) {
245 return;
246 }
247
248 if (c0 == c1) {
249 c1 = AST_LIST_LAST(&bridge->channels)->chan;
250 }
251
252 if (c0 == c1) {
253 return;
254 }
255
256 /* If a party renegotiates we want to renegotiate their counterpart to a matching
257 * topology.
258 */
259 ast_channel_lock_both(c0, c1);
261 existing_top = ast_channel_get_stream_topology(c1);
262 new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
265
266 if (!new_top) {
267 /* Failure. We'll just have to live with the current topology. */
268 return;
269 }
270
273}
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.
struct ast_channel * chan
struct ast_bridge_channel * bridge_channel

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, simple_bridge, and simple_bridge_request_stream_topology_update().

◆ simple_bridge_write()

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

Definition at line 197 of file bridge_simple.c.

198{
199 const struct ast_control_t38_parameters *t38_parameters;
200 int defer = 0;
201
202 if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
203 /* This frame was successfully queued so no need to defer */
204 return 0;
205 }
206
207 /* Depending on the frame defer it so when the next channel joins it receives it */
208 switch (frame->frametype) {
210 switch (frame->subclass.integer) {
212 t38_parameters = frame->data.ptr;
213 switch (t38_parameters->request_response) {
215 defer = -1;
216 break;
217 default:
218 break;
219 }
220 break;
221 default:
222 break;
223 }
224 break;
225 default:
226 break;
227 }
228
229 return defer;
230}
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.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 275 of file bridge_simple.c.

276{
278 return 0;
279}
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 simple_bridge.

Referenced by load_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Simple two channel 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 290 of file bridge_simple.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 290 of file bridge_simple.c.

◆ simple_bridge

struct ast_bridge_technology simple_bridge
static