Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
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 = ASTERISK_GPL_KEY , .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
#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)
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:11010
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition channel.c:6715
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition channel.h:2989
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:4270
#define ast_channel_unlock(chan)
Definition channel.h:2983
@ AST_CONTROL_UNHOLD
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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:939
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition stream.c:768
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition stream.c:746
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:699
#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:367
Main Channel structure associated with a channel.
struct ast_bridge * bridge
#define SWAP(a, b)
Definition utils.h:256

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:791
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:670
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
enum ast_frame_type frametype
union ast_frame::@239 data

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

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 = ASTERISK_GPL_KEY , .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

Definition at line 52 of file bridge_simple.c.

52 {
53 .name = "simple_bridge",
54 .capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
56 .join = simple_bridge_join,
57 .write = simple_bridge_write,
58 .stream_topology_changed = simple_bridge_stream_topology_changed,
59};
@ AST_BRIDGE_CAPABILITY_1TO1MIX
Definition bridge.h:96
static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
@ AST_BRIDGE_PREFERENCE_BASE_1TO1MIX

Referenced by load_module(), simple_bridge_join(), simple_bridge_stream_topology_changed(), and unload_module().