bridges/bridge_t38: Add a bridging module for managing T.38 state
[asterisk/asterisk.git] / bridges / bridge_t38.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@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 Bridging module for maintaining T.38 state for faxing channels
22  *
23  * \author Matt Jordan <mjordan@digium.com>
24  *
25  * \ingroup bridges
26  */
27
28 /*** MODULEINFO
29         <support_level>core</support_level>
30  ***/
31
32 #include "asterisk.h"
33
34 ASTERISK_REGISTER_FILE()
35
36 #include "asterisk/module.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/bridge.h"
39 #include "asterisk/bridge_technology.h"
40 #include "asterisk/frame.h"
41
42 /*! \brief The current state of the T.38 fax for the channels in our bridge */
43 struct t38_bridge_state {
44         /* \brief First channel in the bridge */
45         struct ast_bridge_channel *bc0;
46         /*! \brief Second channel in the bridge */
47         struct ast_bridge_channel *bc1;
48         /*! \brief T.38 state of \c bc0 */
49         enum ast_t38_state c0_state;
50         /*! \brief T.38 state of \c bc1 */
51         enum ast_t38_state c1_state;
52 };
53
54 static void t38_bridge_destroy(struct ast_bridge *bridge)
55 {
56         struct t38_bridge_state *state = bridge->tech_pvt;
57
58         ast_free(state);
59         bridge->tech_pvt = NULL;
60 }
61
62 static int t38_bridge_create(struct ast_bridge *bridge)
63 {
64         struct t38_bridge_state *state;
65
66         state = ast_calloc(1, sizeof(*state));
67         if (!state) {
68                 return -1;
69         }
70
71         bridge->tech_pvt = state;
72
73         return 0;
74 }
75
76 static int t38_bridge_start(struct ast_bridge *bridge)
77 {
78         struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
79         struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
80         struct t38_bridge_state *state = bridge->tech_pvt;
81
82         state->bc0 = bc0;
83         state->bc1 = bc1;
84         state->c0_state = ast_channel_get_t38_state(state->bc0->chan);
85         state->c1_state = ast_channel_get_t38_state(state->bc1->chan);
86
87         return 0;
88 }
89
90 static void send_termination_update(struct ast_bridge *bridge,  struct ast_bridge_channel *bridge_channel, enum ast_t38_state chan_state)
91 {
92         /* Inform the other side that T.38 faxing is done */
93         struct ast_control_t38_parameters parameters = { .request_response = 0, };
94
95         if (!bridge_channel) {
96                 return;
97         }
98
99         ast_debug(5, "Bridge %s T.38: Current state of %s is %d\n",
100                 bridge->uniqueid, ast_channel_name(bridge_channel->chan), chan_state);
101         if (chan_state == T38_STATE_NEGOTIATING) {
102                 parameters.request_response = AST_T38_REFUSED;
103         } else if (chan_state == T38_STATE_NEGOTIATED) {
104                 parameters.request_response = AST_T38_TERMINATED;
105         }
106
107         if (parameters.request_response) {
108                 struct ast_frame f = {
109                         .frametype = AST_FRAME_CONTROL,
110                         .subclass.integer = AST_CONTROL_T38_PARAMETERS,
111                         .data.ptr = &parameters,
112                         .datalen = sizeof(parameters),
113                 };
114
115                 /* When sending a termination update to a channel, the bridge is highly
116                  * likely to be getting torn down. Queueing a frame through the bridging
117                  * framework won't work, as the frame will likely just get tossed as the
118                  * bridge collapses. Hence, we write directly to the channel to ensure that
119                  * they know they aren't in a T.38 fax any longer.
120                  */
121                 ast_debug(3, "Bridge %s T.38: Informing %s to switch to %d\n",
122                         bridge->uniqueid, ast_channel_name(bridge_channel->chan), parameters.request_response);
123                 ast_write(bridge_channel->chan, &f);
124         }
125 }
126
127 static void t38_bridge_stop(struct ast_bridge *bridge)
128 {
129         struct t38_bridge_state *state = bridge->tech_pvt;
130
131         send_termination_update(bridge, state->bc0, state->c0_state);
132         send_termination_update(bridge, state->bc1, state->c1_state);
133 }
134
135 static void t38_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
136 {
137         struct t38_bridge_state *state = bridge->tech_pvt;
138
139         if (bridge_channel == state->bc0) {
140                 send_termination_update(bridge, state->bc0, state->c0_state);
141                 state->bc0 = NULL;
142                 state->c0_state = T38_STATE_UNKNOWN;
143         } else {
144                 send_termination_update(bridge, state->bc1, state->c1_state);
145                 state->bc1 = NULL;
146                 state->c1_state = T38_STATE_UNKNOWN;
147         }
148 }
149
150 static int t38_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
151 {
152         struct t38_bridge_state *state = bridge->tech_pvt;
153         enum ast_t38_state *c_state;
154         enum ast_t38_state *other_state;
155
156         if (!bridge_channel) {
157                 return -1;
158         }
159
160         c_state = bridge_channel == state->bc0 ? &(state->c0_state) : &(state->c1_state);
161         other_state = bridge_channel == state->bc0 ? &(state->c1_state) : &(state->c0_state);
162
163         switch (frame->frametype) {
164         case AST_FRAME_CONTROL:
165                 switch (frame->subclass.integer) {
166                 case AST_CONTROL_T38_PARAMETERS:
167                 {
168                         struct ast_control_t38_parameters *parameters = frame->data.ptr;
169
170                         switch (parameters->request_response) {
171                         case AST_T38_REQUEST_NEGOTIATE:
172                                 *c_state = T38_STATE_NEGOTIATING;
173                                 *other_state = T38_STATE_NEGOTIATING;
174                                 break;
175                         case AST_T38_NEGOTIATED:
176                                 *c_state = T38_STATE_NEGOTIATED;
177                                 break;
178                         case AST_T38_TERMINATED:
179                         case AST_T38_REQUEST_TERMINATE:
180                         case AST_T38_REFUSED:
181                                 *c_state = T38_STATE_REJECTED;
182                                 break;
183                         case AST_T38_REQUEST_PARMS:
184                         default:
185                                 /* No state change */
186                                 break;
187                         }
188                         ast_debug(3, "Bridge %s T.38 state: %s: %d; %s: %d\n",
189                                 bridge->uniqueid, ast_channel_name(state->bc0->chan), state->c0_state,
190                                 ast_channel_name(state->bc1->chan), state->c1_state);
191                         break;
192                 }
193                 default:
194                         break;
195                 }
196                 break;
197         default:
198                 break;
199         }
200
201         return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
202 }
203
204 static int t38_bridge_compatible(struct ast_bridge *bridge)
205 {
206         struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
207         struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
208         enum ast_t38_state c0_state;
209         enum ast_t38_state c1_state;
210
211         /* We must have two, and only two, channels in a T.38 bridge */
212         if (bridge->num_channels != 2) {
213                 ast_debug(1, "Bridge '%s' can not use T.38 bridge as two channels are required\n",
214                         bridge->uniqueid);
215                 return 0;
216         }
217
218         /* We can be the bridge tech so long as one side is in the process
219          * of negotiating T.38
220          */
221         c0_state = ast_channel_get_t38_state(bc0->chan);
222         c1_state = ast_channel_get_t38_state(bc1->chan);
223         if (c0_state != T38_STATE_NEGOTIATING && c0_state != T38_STATE_NEGOTIATED
224             && c1_state != T38_STATE_NEGOTIATING && c1_state != T38_STATE_NEGOTIATED) {
225                 ast_debug(1, "Bridge '%s' can not use T.38 bridge: channel %s has T.38 state %d; channel %s has T.38 state %d\n",
226                         bridge->uniqueid, ast_channel_name(bc0->chan), c0_state, ast_channel_name(bc1->chan), c1_state);
227                 return 0;
228         }
229
230         return 1;
231 }
232
233 static struct ast_bridge_technology t38_bridge = {
234         .name = "t38_bridge",
235         .capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
236         .preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX + 1,
237         .create = t38_bridge_create,
238         .destroy = t38_bridge_destroy,
239         .start = t38_bridge_start,
240         .stop = t38_bridge_stop,
241         .leave = t38_bridge_leave,
242         .write = t38_bridge_write,
243         .compatible = t38_bridge_compatible,
244 };
245
246 static int unload_module(void)
247 {
248         ast_bridge_technology_unregister(&t38_bridge);
249
250         return 0;
251 }
252
253 static int load_module(void)
254 {
255         if (ast_bridge_technology_register(&t38_bridge)) {
256                 return AST_MODULE_LOAD_DECLINE;
257         }
258         return AST_MODULE_LOAD_SUCCESS;
259 }
260
261 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Two channel bridging module that maintains T.38 state");