Asterisk - The Open Source Telephony Project  GIT-master-a24979a
bridge_simple.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Simple two channel bridging module
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  *
25  * \ingroup bridges
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 
40 #include "asterisk/module.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/bridge.h"
44 #include "asterisk/frame.h"
45 #include "asterisk/stream.h"
46 
47 static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
48  struct ast_bridge_channel *bridge_channel);
49 static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
50 static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
51 
52 static struct ast_bridge_technology simple_bridge = {
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 };
60 
62  struct ast_stream_topology *existing_topology,
63  struct ast_stream_topology *requested_topology)
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 }
123 
124 static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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);
149  req_top = ast_channel_get_stream_topology(c0);
150  existing_top = ast_channel_get_stream_topology(c1);
151  if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
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 
168  ast_channel_unlock(c0);
169  ast_channel_unlock(c1);
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 
185  ast_stream_topology_free(new_top);
186 
187  return 0;
188 }
189 
191 {
192  const struct ast_control_t38_parameters *t38_parameters;
193  int defer = 0;
194 
195  if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
196  /* This frame was successfully queued so no need to defer */
197  return 0;
198  }
199 
200  /* Depending on the frame defer it so when the next channel joins it receives it */
201  switch (frame->frametype) {
202  case AST_FRAME_CONTROL:
203  switch (frame->subclass.integer) {
205  t38_parameters = frame->data.ptr;
206  switch (t38_parameters->request_response) {
208  defer = -1;
209  break;
210  default:
211  break;
212  }
213  break;
214  default:
215  break;
216  }
217  break;
218  default:
219  break;
220  }
221 
222  return defer;
223 }
224 
226  struct ast_bridge_channel *bridge_channel)
227 {
228  struct ast_channel *c0 = bridge_channel->chan;
229  struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
230  struct ast_stream_topology *req_top;
231  struct ast_stream_topology *existing_top;
232  struct ast_stream_topology *new_top;
233 
234  ast_bridge_channel_stream_map(bridge_channel);
235 
237  == &simple_bridge) {
238  return;
239  }
240 
241  if (c0 == c1) {
242  c1 = AST_LIST_LAST(&bridge->channels)->chan;
243  }
244 
245  if (c0 == c1) {
246  return;
247  }
248 
249  /* If a party renegotiates we want to renegotiate their counterpart to a matching
250  * topology.
251  */
252  ast_channel_lock_both(c0, c1);
253  req_top = ast_channel_get_stream_topology(c0);
254  existing_top = ast_channel_get_stream_topology(c1);
255  new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
256  ast_channel_unlock(c0);
257  ast_channel_unlock(c1);
258 
259  if (!new_top) {
260  /* Failure. We'll just have to live with the current topology. */
261  return;
262  }
263 
265  ast_stream_topology_free(new_top);
266 }
267 
268 static int unload_module(void)
269 {
271  return 0;
272 }
273 
274 static int load_module(void)
275 {
277  unload_module();
279  }
281 }
282 
283 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple two channel bridging module");
Asterisk main include file. File version handling, generic pbx functions.
Bridging API.
@ AST_BRIDGE_CAPABILITY_1TO1MIX
Definition: bridge.h:92
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.
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel's stream topology to and from the bridge.
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 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
static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static int load_module(void)
static int unload_module(void)
static struct ast_bridge_technology simple_bridge
Definition: bridge_simple.c:52
Channel Bridging API.
@ AST_BRIDGE_PREFERENCE_BASE_1TO1MIX
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:263
General Asterisk PBX channel definitions.
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:11152
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6798
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
const char * ast_channel_name(const struct ast_channel *chan)
void * ast_channel_get_stream_topology_change_source(struct ast_channel *chan)
Retrieve the source that initiated the last stream topology change.
int ast_channel_hold_state(const struct ast_channel *chan)
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4312
#define ast_channel_unlock(chan)
Definition: channel.h:2923
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
Asterisk internal frame definitions.
@ AST_T38_REQUEST_NEGOTIATE
@ AST_FRAME_CONTROL
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_T38_PARAMETERS
@ 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
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ 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
#define NULL
Definition: resample.c:96
Media Stream API.
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
@ 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
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
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_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
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
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
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
Structure that contains information regarding a channel in a bridge.
struct ast_channel * chan
Structure that is the essence of a bridge technology.
Structure that contains information about a bridge.
Definition: bridge.h:349
struct ast_bridge_channels_list channels
Definition: bridge.h:363
Main Channel structure associated with a channel.
struct ast_bridge_channel * bridge_channel
struct ast_bridge * bridge
enum ast_control_t38 request_response
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@254 data
enum ast_frame_type frametype
#define SWAP(a, b)
Definition: utils.h:230