Asterisk - The Open Source Telephony Project  18.5.0
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 262 of file bridge_simple.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 262 of file bridge_simple.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 262 of file bridge_simple.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 253 of file bridge_simple.c.

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

254 {
256  unload_module();
258  }
260 }
static struct ast_bridge_technology simple_bridge
Definition: bridge_simple.c:52
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int unload_module(void)

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

References ast_channel_get_stream_topology(), ast_channel_lock_both, ast_channel_make_compatible(), ast_channel_request_stream_topology_change(), ast_channel_unlock, AST_LIST_FIRST, AST_LIST_LAST, ast_stream_topology_free(), ast_stream_topology_get_count(), ast_bridge::channels, simple_bridge_request_stream_topology_update(), and SWAP.

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 
132  /*
133  * If this is the first channel we can't make it compatible...
134  * unless we make it compatible with itself. O.o
135  */
136  if (c0 == c1) {
137  return 0;
138  }
139 
140  if (ast_channel_make_compatible(c0, c1)) {
141  return -1;
142  }
143 
144  /* When both channels are joined we want to try to improve the experience by
145  * raising the number of streams so they match.
146  */
147  ast_channel_lock_both(c0, c1);
148  req_top = ast_channel_get_stream_topology(c0);
149  existing_top = ast_channel_get_stream_topology(c1);
150  if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
151  SWAP(req_top, existing_top);
152  SWAP(c0, c1);
153  }
154  new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
155  ast_channel_unlock(c0);
156  ast_channel_unlock(c1);
157 
158  if (!new_top) {
159  /* Failure. We'll just have to live with the current topology. */
160  return 0;
161  }
162 
164  ast_stream_topology_free(new_top);
165 
166  return 0;
167 }
Main Channel structure associated with a channel.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
static struct ast_bridge_technology simple_bridge
Definition: bridge_simple.c:52
#define SWAP(a, b)
Definition: utils.h:230
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:11167
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6817
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
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
struct ast_bridge_channels_list channels
Definition: bridge.h:371
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743

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

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().

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 }
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
Set when the stream has been removed/declined.
Definition: stream.h:78
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
#define NULL
Definition: resample.c:96
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
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
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
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
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
Set when the stream is receiving media only.
Definition: stream.h:90
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373

◆ 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 204 of file bridge_simple.c.

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_bridge_channel::chan, ast_bridge::channels, and simple_bridge_request_stream_topology_update().

206 {
207  struct ast_channel *c0 = bridge_channel->chan;
208  struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
209  struct ast_stream_topology *req_top;
210  struct ast_stream_topology *existing_top;
211  struct ast_stream_topology *new_top;
212 
213  ast_bridge_channel_stream_map(bridge_channel);
214 
216  == &simple_bridge) {
217  return;
218  }
219 
220  if (c0 == c1) {
221  c1 = AST_LIST_LAST(&bridge->channels)->chan;
222  }
223 
224  if (c0 == c1) {
225  return;
226  }
227 
228  /* If a party renegotiates we want to renegotiate their counterpart to a matching
229  * topology.
230  */
231  ast_channel_lock_both(c0, c1);
232  req_top = ast_channel_get_stream_topology(c0);
233  existing_top = ast_channel_get_stream_topology(c1);
234  new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
235  ast_channel_unlock(c0);
236  ast_channel_unlock(c1);
237 
238  if (!new_top) {
239  /* Failure. We'll just have to live with the current topology. */
240  return;
241  }
242 
244  ast_stream_topology_free(new_top);
245 }
Main Channel structure associated with a channel.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
static struct ast_bridge_technology simple_bridge
Definition: bridge_simple.c:52
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:11167
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
void * ast_channel_get_stream_topology_change_source(struct ast_channel *chan)
Retrieve the source that initiated the last stream topology change.
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct ast_channel * chan
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel&#39;s stream topology to and from the bridge.
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743

◆ 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 169 of file bridge_simple.c.

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.

170 {
171  const struct ast_control_t38_parameters *t38_parameters;
172  int defer = 0;
173 
174  if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
175  /* This frame was successfully queued so no need to defer */
176  return 0;
177  }
178 
179  /* Depending on the frame defer it so when the next channel joins it receives it */
180  switch (frame->frametype) {
181  case AST_FRAME_CONTROL:
182  switch (frame->subclass.integer) {
184  t38_parameters = frame->data.ptr;
185  switch (t38_parameters->request_response) {
187  defer = -1;
188  break;
189  default:
190  break;
191  }
192  break;
193  default:
194  break;
195  }
196  break;
197  default:
198  break;
199  }
200 
201  return defer;
202 }
enum ast_control_t38 request_response
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.
struct ast_frame_subclass subclass
union ast_frame::@263 data
enum ast_frame_type frametype

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 247 of file bridge_simple.c.

References ast_bridge_technology_unregister().

Referenced by load_module().

248 {
250  return 0;
251 }
static struct ast_bridge_technology simple_bridge
Definition: bridge_simple.c:52
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:265

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 262 of file bridge_simple.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 262 of file bridge_simple.c.

◆ simple_bridge

struct ast_bridge_technology simple_bridge
static

Definition at line 52 of file bridge_simple.c.