logger.conf.sample: add missing comment mark
[asterisk/asterisk.git] / bridges / bridge_simple.c
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"
43 #include "asterisk/bridge_technology.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,
55         .preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX,
56         .join = simple_bridge_join,
57         .write = simple_bridge_write,
58         .stream_topology_changed = simple_bridge_stream_topology_changed,
59 };
60
61 static struct ast_stream_topology *simple_bridge_request_stream_topology_update(
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
82                 if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
83                         ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
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
95                         if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
96                                 ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
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                  */
114                 if (ast_stream_get_state(stream) == AST_STREAM_STATE_RECVONLY) {
115                         ast_stream_set_state(stream, AST_STREAM_STATE_SENDONLY);
116                 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
117                         ast_stream_set_state(stream, AST_STREAM_STATE_RECVONLY);
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
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
163         ast_channel_request_stream_topology_change(c1, new_top, &simple_bridge);
164         ast_stream_topology_free(new_top);
165
166         return 0;
167 }
168
169 static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
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) {
183                 case AST_CONTROL_T38_PARAMETERS:
184                         t38_parameters = frame->data.ptr;
185                         switch (t38_parameters->request_response) {
186                         case AST_T38_REQUEST_NEGOTIATE:
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 }
203
204 static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
205                 struct ast_bridge_channel *bridge_channel)
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
215         if (ast_channel_get_stream_topology_change_source(bridge_channel->chan)
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
243         ast_channel_request_stream_topology_change(c1, new_top, &simple_bridge);
244         ast_stream_topology_free(new_top);
245 }
246
247 static int unload_module(void)
248 {
249         ast_bridge_technology_unregister(&simple_bridge);
250         return 0;
251 }
252
253 static int load_module(void)
254 {
255         if (ast_bridge_technology_register(&simple_bridge)) {
256                 unload_module();
257                 return AST_MODULE_LOAD_DECLINE;
258         }
259         return AST_MODULE_LOAD_SUCCESS;
260 }
261
262 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple two channel bridging module");