Asterisk - The Open Source Telephony Project GIT-master-9647a4f
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 292 of file bridge_simple.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 292 of file bridge_simple.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 292 of file bridge_simple.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 283 of file bridge_simple.c.

284{
288 }
290}
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 unhold_c1 = (ast_channel_hold_state(c1) == AST_CONTROL_HOLD);
161 if (unhold_c1) {
162 ast_debug(1, "Channel %s simulating UNHOLD for bridge simple join.\n", ast_channel_name(c1));
163 }
164
165 unhold_c0 = (ast_channel_hold_state(c0) == AST_CONTROL_HOLD);
166 if (unhold_c0) {
167 ast_debug(1, "Channel %s simulating UNHOLD for bridge simple join.\n", ast_channel_name(c0));
168 }
169
172
173 if (unhold_c1) {
175 }
176
177 if (unhold_c0) {
179 }
180
181 if (!new_top) {
182 /* Failure. We'll just have to live with the current topology. */
183 return 0;
184 }
185
186 if (!ast_stream_topology_equal(new_top, existing_top)) {
188 } else {
189 ast_debug(3, "%s: Topologies already match. Current: %s Requested: %s\n",
191 ast_str_tmp(256, ast_stream_topology_to_str(existing_top, &STR_TMP)),
192 ast_str_tmp(256, ast_stream_topology_to_str(new_top, &STR_TMP)));
193 }
195
196 return 0;
197}
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:11014
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 234 of file bridge_simple.c.

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

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

278{
280 return 0;
281}
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 292 of file bridge_simple.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 292 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().