4af93bfca21cc0a28ea64fce48a4ec7368ebf0b9
[asterisk/asterisk.git] / bridges / bridge_native_rtp.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, 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 Native RTP bridging technology 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/rtp_engine.h"
46
47 /*! \brief Internal structure which contains information about bridged RTP channels */
48 struct native_rtp_bridge_data {
49         /*! \brief Framehook used to intercept certain control frames */
50         int id;
51         /*! \brief Set when this framehook has been detached */
52         unsigned int detached;
53 };
54
55 /*! \brief Internal helper function which gets all RTP information (glue and instances) relating to the given channels */
56 static enum ast_rtp_glue_result native_rtp_bridge_get(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp_glue **glue0,
57         struct ast_rtp_glue **glue1, struct ast_rtp_instance **instance0, struct ast_rtp_instance **instance1,
58         struct ast_rtp_instance **vinstance0, struct ast_rtp_instance **vinstance1)
59 {
60         enum ast_rtp_glue_result audio_glue0_res;
61         enum ast_rtp_glue_result video_glue0_res;
62         enum ast_rtp_glue_result audio_glue1_res;
63         enum ast_rtp_glue_result video_glue1_res;
64
65         if (!(*glue0 = ast_rtp_instance_get_glue(ast_channel_tech(c0)->type)) ||
66                 !(*glue1 = ast_rtp_instance_get_glue(ast_channel_tech(c1)->type))) {
67                 return AST_RTP_GLUE_RESULT_FORBID;
68         }
69
70         audio_glue0_res = (*glue0)->get_rtp_info(c0, instance0);
71         video_glue0_res = (*glue0)->get_vrtp_info ? (*glue0)->get_vrtp_info(c0, vinstance0) : AST_RTP_GLUE_RESULT_FORBID;
72
73         audio_glue1_res = (*glue1)->get_rtp_info(c1, instance1);
74         video_glue1_res = (*glue1)->get_vrtp_info ? (*glue1)->get_vrtp_info(c1, vinstance1) : AST_RTP_GLUE_RESULT_FORBID;
75
76         /* Apply any limitations on direct media bridging that may be present */
77         if (audio_glue0_res == audio_glue1_res && audio_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) {
78                 if ((*glue0)->allow_rtp_remote && !((*glue0)->allow_rtp_remote(c0, *instance1))) {
79                         /* If the allow_rtp_remote indicates that remote isn't allowed, revert to local bridge */
80                         audio_glue0_res = audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
81                 } else if ((*glue1)->allow_rtp_remote && !((*glue1)->allow_rtp_remote(c1, *instance0))) {
82                         audio_glue0_res = audio_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
83                 }
84         }
85         if (video_glue0_res == video_glue1_res && video_glue1_res == AST_RTP_GLUE_RESULT_REMOTE) {
86                 if ((*glue0)->allow_vrtp_remote && !((*glue0)->allow_vrtp_remote(c0, *instance1))) {
87                         /* if the allow_vrtp_remote indicates that remote isn't allowed, revert to local bridge */
88                         video_glue0_res = video_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
89                 } else if ((*glue1)->allow_vrtp_remote && !((*glue1)->allow_vrtp_remote(c1, *instance0))) {
90                         video_glue0_res = video_glue1_res = AST_RTP_GLUE_RESULT_LOCAL;
91                 }
92         }
93
94         /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
95         if (video_glue0_res != AST_RTP_GLUE_RESULT_FORBID
96                 && (audio_glue0_res != AST_RTP_GLUE_RESULT_REMOTE
97                         || video_glue0_res != AST_RTP_GLUE_RESULT_REMOTE)) {
98                 audio_glue0_res = AST_RTP_GLUE_RESULT_FORBID;
99         }
100         if (video_glue1_res != AST_RTP_GLUE_RESULT_FORBID
101                 && (audio_glue1_res != AST_RTP_GLUE_RESULT_REMOTE
102                         || video_glue1_res != AST_RTP_GLUE_RESULT_REMOTE)) {
103                 audio_glue1_res = AST_RTP_GLUE_RESULT_FORBID;
104         }
105
106         /* The order of preference is: forbid, local, and remote. */
107         if (audio_glue0_res == AST_RTP_GLUE_RESULT_FORBID ||
108                 audio_glue1_res == AST_RTP_GLUE_RESULT_FORBID) {
109                 /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
110                 return AST_RTP_GLUE_RESULT_FORBID;
111         } else if (audio_glue0_res == AST_RTP_GLUE_RESULT_LOCAL ||
112                 audio_glue1_res == AST_RTP_GLUE_RESULT_LOCAL) {
113                 return AST_RTP_GLUE_RESULT_LOCAL;
114         } else {
115                 return AST_RTP_GLUE_RESULT_REMOTE;
116         }
117 }
118
119 /*!
120  * \internal
121  * \brief Start native RTP bridging of two channels
122  *
123  * \param bridge The bridge that had native RTP bridging happening on it
124  * \param target If remote RTP bridging, the channel that is unheld.
125  *
126  * \note Bridge must be locked when calling this function.
127  */
128 static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channel *target)
129 {
130         struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
131         struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
132         enum ast_rtp_glue_result native_type = AST_RTP_GLUE_RESULT_FORBID;
133         struct ast_rtp_glue *glue0, *glue1;
134         RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
135         RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
136         RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
137         RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
138         RAII_VAR(struct ast_rtp_instance *, tinstance0, NULL, ao2_cleanup);
139         RAII_VAR(struct ast_rtp_instance *, tinstance1, NULL, ao2_cleanup);
140         RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
141         RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
142
143         if (bc0 == bc1) {
144                 return;
145         }
146
147         ast_channel_lock_both(bc0->chan, bc1->chan);
148         if (!bc0->suspended && !bc1->suspended) {
149                 native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1);
150         }
151
152         switch (native_type) {
153         case AST_RTP_GLUE_RESULT_LOCAL:
154                 if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
155                         ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, instance1);
156                 }
157                 if (ast_rtp_instance_get_engine(instance1)->local_bridge) {
158                         ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, instance0);
159                 }
160                 ast_rtp_instance_set_bridged(instance0, instance1);
161                 ast_rtp_instance_set_bridged(instance1, instance0);
162                 ast_verb(4, "Locally RTP bridged '%s' and '%s' in stack\n",
163                         ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
164                 break;
165
166         case AST_RTP_GLUE_RESULT_REMOTE:
167                 if (glue0->get_codec) {
168                         glue0->get_codec(bc0->chan, cap0);
169                 }
170                 if (glue1->get_codec) {
171                         glue1->get_codec(bc1->chan, cap1);
172                 }
173
174                 /* If we have a target, it's the channel that received the UNHOLD or UPDATE_RTP_PEER frame and was told to resume */
175                 if (!target) {
176                         glue0->update_peer(bc0->chan, instance1, vinstance1, tinstance1, cap1, 0);
177                         glue1->update_peer(bc1->chan, instance0, vinstance0, tinstance0, cap0, 0);
178                         ast_verb(4, "Remotely bridged '%s' and '%s' - media will flow directly between them\n",
179                                 ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
180                 } else {
181                         /*
182                          * If a target was provided, it is the recipient of an unhold or an update and needs to have
183                          * its media redirected to fit the current remote bridging needs. The other channel is either
184                          * already set up to handle the new media path or will have its own set of updates independent
185                          * of this pass.
186                          */
187                         if (bc0->chan == target) {
188                                 glue0->update_peer(bc0->chan, instance1, vinstance1, tinstance1, cap1, 0);
189                         } else {
190                                 glue1->update_peer(bc1->chan, instance0, vinstance0, tinstance0, cap0, 0);
191                         }
192                 }
193                 break;
194         case AST_RTP_GLUE_RESULT_FORBID:
195                 break;
196         }
197
198         ast_channel_unlock(bc0->chan);
199         ast_channel_unlock(bc1->chan);
200 }
201
202 static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
203 {
204         struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
205         struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
206         enum ast_rtp_glue_result native_type;
207         struct ast_rtp_glue *glue0, *glue1 = NULL;
208         RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
209         RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
210         RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
211         RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
212
213         if (bc0 == bc1) {
214                 return;
215         }
216
217         ast_channel_lock_both(bc0->chan, bc1->chan);
218         native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1);
219
220         switch (native_type) {
221         case AST_RTP_GLUE_RESULT_LOCAL:
222                 if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
223                         ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, NULL);
224                 }
225                 if (instance1 && ast_rtp_instance_get_engine(instance1)->local_bridge) {
226                         ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, NULL);
227                 }
228                 ast_rtp_instance_set_bridged(instance0, NULL);
229                 if (instance1) {
230                         ast_rtp_instance_set_bridged(instance1, NULL);
231                 }
232                 break;
233         case AST_RTP_GLUE_RESULT_REMOTE:
234                 if (target) {
235                         /*
236                          * If a target was provided, it is being put on hold and should expect to
237                          * receive media from Asterisk instead of what it was previously connected to.
238                          */
239                         if (bc0->chan == target) {
240                                 glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
241                         } else {
242                                 glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
243                         }
244                 }
245                 break;
246         case AST_RTP_GLUE_RESULT_FORBID:
247                 break;
248         }
249
250         if (!target && native_type != AST_RTP_GLUE_RESULT_FORBID) {
251                 glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
252                 glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
253         }
254
255         ast_debug(2, "Discontinued RTP bridging of '%s' and '%s' - media will flow through Asterisk core\n",
256                 ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
257
258         ast_channel_unlock(bc0->chan);
259         ast_channel_unlock(bc1->chan);
260 }
261
262 /*! \brief Frame hook that is called to intercept hold/unhold */
263 static struct ast_frame *native_rtp_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
264 {
265         RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
266         struct native_rtp_bridge_data *native_data = data;
267
268         if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
269                 return f;
270         }
271
272         bridge = ast_channel_get_bridge(chan);
273         if (bridge) {
274                 /* native_rtp_bridge_start/stop are not being called from bridging
275                    core so we need to lock the bridge prior to calling these functions
276                    Unfortunately that means unlocking the channel, but as it
277                    should not be modified this should be okay... hopefully...
278                    unless this channel is being moved around right now and is in
279                    the process of having this framehook removed (which is fine). To
280                    ensure we then don't stop or start when we shouldn't we consult
281                    the data provided. If this framehook has been detached then the
282                    detached variable will be set. This is safe to check as it is only
283                    manipulated with the bridge lock held. */
284                 ast_channel_unlock(chan);
285                 ast_bridge_lock(bridge);
286                 if (!native_data->detached) {
287                         if (f->subclass.integer == AST_CONTROL_HOLD) {
288                                 native_rtp_bridge_stop(bridge, chan);
289                         } else if ((f->subclass.integer == AST_CONTROL_UNHOLD) ||
290                                 (f->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) {
291                                 native_rtp_bridge_start(bridge, chan);
292                         }
293                 }
294                 ast_bridge_unlock(bridge);
295                 ast_channel_lock(chan);
296
297         }
298
299         return f;
300 }
301
302 /*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
303 static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
304 {
305         return (type == AST_FRAME_CONTROL ? 1 : 0);
306 }
307
308 /*! \brief Internal helper function which checks whether the channels are compatible with our native bridging */
309 static int native_rtp_bridge_capable(struct ast_channel *chan)
310 {
311         return !ast_channel_has_hook_requiring_audio(chan);
312 }
313
314 static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
315 {
316         enum ast_rtp_glue_result native_type;
317         struct ast_rtp_glue *glue0;
318         struct ast_rtp_glue *glue1;
319         RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
320         RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
321         RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
322         RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
323         RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup);
324         RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup);
325         int read_ptime0;
326         int read_ptime1;
327         int write_ptime0;
328         int write_ptime1;
329
330         if (!native_rtp_bridge_capable(bc0->chan)) {
331                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
332                         bridge->uniqueid, ast_channel_name(bc0->chan));
333                 return 0;
334         }
335
336         if (!native_rtp_bridge_capable(bc1->chan)) {
337                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
338                         bridge->uniqueid, ast_channel_name(bc1->chan));
339                 return 0;
340         }
341
342         native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1,
343                 &instance0, &instance1, &vinstance0, &vinstance1);
344         if (native_type == AST_RTP_GLUE_RESULT_FORBID) {
345                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
346                         bridge->uniqueid);
347                 return 0;
348         }
349
350         if (ao2_container_count(bc0->features->dtmf_hooks)
351                 && ast_rtp_instance_dtmf_mode_get(instance0)) {
352                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
353                         bridge->uniqueid, ast_channel_name(bc0->chan));
354                 return 0;
355         }
356
357         if (ao2_container_count(bc1->features->dtmf_hooks)
358                 && ast_rtp_instance_dtmf_mode_get(instance1)) {
359                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
360                         bridge->uniqueid, ast_channel_name(bc1->chan));
361                 return 0;
362         }
363
364         if (native_type == AST_RTP_GLUE_RESULT_LOCAL
365                 && (ast_rtp_instance_get_engine(instance0)->local_bridge
366                         != ast_rtp_instance_get_engine(instance1)->local_bridge
367                         || (ast_rtp_instance_get_engine(instance0)->dtmf_compatible
368                                 && !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(bc0->chan,
369                                         instance0, bc1->chan, instance1)))) {
370                 ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
371                         bridge->uniqueid);
372                 return 0;
373         }
374
375         cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
376         cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
377         if (!cap0 || !cap1) {
378                 return 0;
379         }
380
381         /* Make sure that codecs match */
382         if (glue0->get_codec) {
383                 glue0->get_codec(bc0->chan, cap0);
384         }
385         if (glue1->get_codec) {
386                 glue1->get_codec(bc1->chan, cap1);
387         }
388         if (ast_format_cap_count(cap0) != 0
389                 && ast_format_cap_count(cap1) != 0
390                 && !ast_format_cap_iscompatible(cap0, cap1)) {
391                 struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
392                 struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
393
394                 ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
395                         bridge->uniqueid,
396                         ast_format_cap_get_names(cap0, &codec_buf0),
397                         ast_format_cap_get_names(cap1, &codec_buf1));
398                 return 0;
399         }
400
401         read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan));
402         read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(bc1->chan));
403         write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(bc0->chan));
404         write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(bc1->chan));
405
406         if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
407                 ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
408                         bridge->uniqueid,
409                         read_ptime0, write_ptime1, read_ptime1, write_ptime0);
410                 return 0;
411         }
412
413         return 1;
414 }
415
416 static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
417 {
418         struct ast_bridge_channel *bc0;
419         struct ast_bridge_channel *bc1;
420         int is_compatible;
421
422         /* We require two channels before even considering native bridging */
423         if (bridge->num_channels != 2) {
424                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as two channels are required\n",
425                         bridge->uniqueid);
426                 return 0;
427         }
428
429         bc0 = AST_LIST_FIRST(&bridge->channels);
430         bc1 = AST_LIST_LAST(&bridge->channels);
431
432         ast_channel_lock_both(bc0->chan, bc1->chan);
433         is_compatible = native_rtp_bridge_compatible_check(bridge, bc0, bc1);
434         ast_channel_unlock(bc0->chan);
435         ast_channel_unlock(bc1->chan);
436
437         return is_compatible;
438 }
439
440 /*! \brief Helper function which adds frame hook to bridge channel */
441 static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
442 {
443         struct native_rtp_bridge_data *data = ao2_alloc(sizeof(*data), NULL);
444         static struct ast_framehook_interface hook = {
445                 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
446                 .event_cb = native_rtp_framehook,
447                 .destroy_cb = __ao2_cleanup,
448                 .consume_cb = native_rtp_framehook_consume,
449                 .disable_inheritance = 1,
450         };
451
452         if (!data) {
453                 return -1;
454         }
455
456         ast_channel_lock(bridge_channel->chan);
457         hook.data = ao2_bump(data);
458         data->id = ast_framehook_attach(bridge_channel->chan, &hook);
459         ast_channel_unlock(bridge_channel->chan);
460         if (data->id < 0) {
461                 /* We need to drop both the reference we hold, and the one the framehook would hold */
462                 ao2_ref(data, -2);
463                 return -1;
464         }
465
466         bridge_channel->tech_pvt = data;
467
468         return 0;
469 }
470
471 /*! \brief Helper function which removes frame hook from bridge channel */
472 static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
473 {
474         RAII_VAR(struct native_rtp_bridge_data *, data, bridge_channel->tech_pvt, ao2_cleanup);
475
476         if (!data) {
477                 return;
478         }
479
480         ast_channel_lock(bridge_channel->chan);
481         ast_framehook_detach(bridge_channel->chan, data->id);
482         data->detached = 1;
483         ast_channel_unlock(bridge_channel->chan);
484         bridge_channel->tech_pvt = NULL;
485 }
486
487 static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
488 {
489         native_rtp_bridge_framehook_detach(bridge_channel);
490         if (native_rtp_bridge_framehook_attach(bridge_channel)) {
491                 return -1;
492         }
493
494         native_rtp_bridge_start(bridge, NULL);
495         return 0;
496 }
497
498 static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
499 {
500         native_rtp_bridge_join(bridge, bridge_channel);
501 }
502
503 static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
504 {
505         native_rtp_bridge_framehook_detach(bridge_channel);
506         native_rtp_bridge_stop(bridge, NULL);
507 }
508
509 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
510 {
511         const struct ast_control_t38_parameters *t38_parameters;
512         int defer = 0;
513
514         if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
515                 /* This frame was successfully queued so no need to defer */
516                 return 0;
517         }
518
519         /* Depending on the frame defer it so when the next channel joins it receives it */
520         switch (frame->frametype) {
521         case AST_FRAME_CONTROL:
522                 switch (frame->subclass.integer) {
523                 case AST_CONTROL_T38_PARAMETERS:
524                         t38_parameters = frame->data.ptr;
525                         switch (t38_parameters->request_response) {
526                         case AST_T38_REQUEST_NEGOTIATE:
527                                 defer = -1;
528                                 break;
529                         default:
530                                 break;
531                         }
532                         break;
533                 default:
534                         break;
535                 }
536                 break;
537         default:
538                 break;
539         }
540
541         return defer;
542 }
543
544 static struct ast_bridge_technology native_rtp_bridge = {
545         .name = "native_rtp",
546         .capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
547         .preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
548         .join = native_rtp_bridge_join,
549         .unsuspend = native_rtp_bridge_unsuspend,
550         .leave = native_rtp_bridge_leave,
551         .suspend = native_rtp_bridge_leave,
552         .write = native_rtp_bridge_write,
553         .compatible = native_rtp_bridge_compatible,
554 };
555
556 static int unload_module(void)
557 {
558         ast_bridge_technology_unregister(&native_rtp_bridge);
559         return 0;
560 }
561
562 static int load_module(void)
563 {
564         if (ast_bridge_technology_register(&native_rtp_bridge)) {
565                 unload_module();
566                 return AST_MODULE_LOAD_DECLINE;
567         }
568         return AST_MODULE_LOAD_SUCCESS;
569 }
570
571 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Native RTP bridging module");