bridge : Fix one-way direct-media when early bridging with native_rtp
[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
50 static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
51 {
52         struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
53         struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
54
55         /*
56          * If this is the first channel we can't make it compatible...
57          * unless we make it compatible with itself.  O.o
58          */
59         if (c0 == c1) {
60                 return 0;
61         }
62
63         if (ast_channel_make_compatible(c0, c1)) {
64                 return -1;
65         }
66
67         /* Align stream topologies */
68         simple_bridge_stream_topology_changed(bridge, NULL);
69         return 0;
70 }
71
72 static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
73 {
74         const struct ast_control_t38_parameters *t38_parameters;
75         int defer = 0;
76
77         if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
78                 /* This frame was successfully queued so no need to defer */
79                 return 0;
80         }
81
82         /* Depending on the frame defer it so when the next channel joins it receives it */
83         switch (frame->frametype) {
84         case AST_FRAME_CONTROL:
85                 switch (frame->subclass.integer) {
86                 case AST_CONTROL_T38_PARAMETERS:
87                         t38_parameters = frame->data.ptr;
88                         switch (t38_parameters->request_response) {
89                         case AST_T38_REQUEST_NEGOTIATE:
90                                 defer = -1;
91                                 break;
92                         default:
93                                 break;
94                         }
95                         break;
96                 default:
97                         break;
98                 }
99                 break;
100         default:
101                 break;
102         }
103
104         return defer;
105 }
106
107 static struct ast_bridge_technology simple_bridge = {
108         .name = "simple_bridge",
109         .capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
110         .preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX,
111         .join = simple_bridge_join,
112         .write = simple_bridge_write,
113         .stream_topology_changed = simple_bridge_stream_topology_changed,
114 };
115
116 static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
117                 struct ast_bridge_channel *bridge_channel)
118 {
119         struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
120         struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
121         struct ast_stream_topology *t0 = ast_channel_get_stream_topology(c0);
122         struct ast_stream_topology *t1 = ast_channel_get_stream_topology(c1);
123
124         if (bridge_channel) {
125                 ast_bridge_channel_stream_map(bridge_channel);
126         }
127         /*
128          * The bridge_channel should only be NULL after both channels join
129          * the bridge and their topologies are being aligned.
130          */
131         if (bridge_channel && ast_channel_get_stream_topology_change_source(
132                     bridge_channel->chan) == &simple_bridge) {
133                 return;
134         }
135
136         /* Align topologies according to size or first channel to join */
137         if (ast_stream_topology_get_count(t0) < ast_stream_topology_get_count(t1)) {
138                 ast_channel_request_stream_topology_change(c0, t1, &simple_bridge);
139         } else {
140                 ast_channel_request_stream_topology_change(c1, t0, &simple_bridge);
141         }
142 }
143
144 static int unload_module(void)
145 {
146         ast_bridge_technology_unregister(&simple_bridge);
147         return 0;
148 }
149
150 static int load_module(void)
151 {
152         if (ast_bridge_technology_register(&simple_bridge)) {
153                 unload_module();
154                 return AST_MODULE_LOAD_DECLINE;
155         }
156         return AST_MODULE_LOAD_SUCCESS;
157 }
158
159 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple two channel bridging module");