Binaural synthesis (confbridge): Adds binaural synthesis to bridge_softmix.
[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;
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         native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1);
149
150         switch (native_type) {
151         case AST_RTP_GLUE_RESULT_LOCAL:
152                 if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
153                         ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, instance1);
154                 }
155                 if (ast_rtp_instance_get_engine(instance1)->local_bridge) {
156                         ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, instance0);
157                 }
158                 ast_rtp_instance_set_bridged(instance0, instance1);
159                 ast_rtp_instance_set_bridged(instance1, instance0);
160                 ast_verb(4, "Locally RTP bridged '%s' and '%s' in stack\n",
161                         ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
162                 break;
163
164         case AST_RTP_GLUE_RESULT_REMOTE:
165                 if (glue0->get_codec) {
166                         glue0->get_codec(bc0->chan, cap0);
167                 }
168                 if (glue1->get_codec) {
169                         glue1->get_codec(bc1->chan, cap1);
170                 }
171
172                 /* If we have a target, it's the channel that received the UNHOLD or UPDATE_RTP_PEER frame and was told to resume */
173                 if (!target) {
174                         glue0->update_peer(bc0->chan, instance1, vinstance1, tinstance1, cap1, 0);
175                         glue1->update_peer(bc1->chan, instance0, vinstance0, tinstance0, cap0, 0);
176                         ast_verb(4, "Remotely bridged '%s' and '%s' - media will flow directly between them\n",
177                                 ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
178                 } else {
179                         /*
180                          * If a target was provided, it is the recipient of an unhold or an update and needs to have
181                          * its media redirected to fit the current remote bridging needs. The other channel is either
182                          * already set up to handle the new media path or will have its own set of updates independent
183                          * of this pass.
184                          */
185                         if (bc0->chan == target) {
186                                 glue0->update_peer(bc0->chan, instance1, vinstance1, tinstance1, cap1, 0);
187                         } else {
188                                 glue1->update_peer(bc1->chan, instance0, vinstance0, tinstance0, cap0, 0);
189                         }
190                 }
191                 break;
192         case AST_RTP_GLUE_RESULT_FORBID:
193                 break;
194         }
195
196         ast_channel_unlock(bc0->chan);
197         ast_channel_unlock(bc1->chan);
198 }
199
200 static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
201 {
202         struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
203         struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
204         enum ast_rtp_glue_result native_type;
205         struct ast_rtp_glue *glue0, *glue1 = NULL;
206         RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
207         RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
208         RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
209         RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
210
211         if (bc0 == bc1) {
212                 return;
213         }
214
215         ast_channel_lock_both(bc0->chan, bc1->chan);
216         native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1);
217
218         switch (native_type) {
219         case AST_RTP_GLUE_RESULT_LOCAL:
220                 if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
221                         ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, NULL);
222                 }
223                 if (instance1 && ast_rtp_instance_get_engine(instance1)->local_bridge) {
224                         ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, NULL);
225                 }
226                 ast_rtp_instance_set_bridged(instance0, NULL);
227                 if (instance1) {
228                         ast_rtp_instance_set_bridged(instance1, NULL);
229                 }
230                 break;
231         case AST_RTP_GLUE_RESULT_REMOTE:
232                 if (target) {
233                         /*
234                          * If a target was provided, it is being put on hold and should expect to
235                          * receive media from Asterisk instead of what it was previously connected to.
236                          */
237                         if (bc0->chan == target) {
238                                 glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
239                         } else {
240                                 glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
241                         }
242                 }
243                 break;
244         case AST_RTP_GLUE_RESULT_FORBID:
245                 break;
246         }
247
248         if (!target && native_type != AST_RTP_GLUE_RESULT_FORBID) {
249                 glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
250                 glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
251         }
252
253         ast_debug(2, "Discontinued RTP bridging of '%s' and '%s' - media will flow through Asterisk core\n",
254                 ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
255
256         ast_channel_unlock(bc0->chan);
257         ast_channel_unlock(bc1->chan);
258 }
259
260 /*! \brief Frame hook that is called to intercept hold/unhold */
261 static struct ast_frame *native_rtp_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
262 {
263         RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
264         struct native_rtp_bridge_data *native_data = data;
265
266         if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
267                 return f;
268         }
269
270         bridge = ast_channel_get_bridge(chan);
271         if (bridge) {
272                 /* native_rtp_bridge_start/stop are not being called from bridging
273                    core so we need to lock the bridge prior to calling these functions
274                    Unfortunately that means unlocking the channel, but as it
275                    should not be modified this should be okay... hopefully...
276                    unless this channel is being moved around right now and is in
277                    the process of having this framehook removed (which is fine). To
278                    ensure we then don't stop or start when we shouldn't we consult
279                    the data provided. If this framehook has been detached then the
280                    detached variable will be set. This is safe to check as it is only
281                    manipulated with the bridge lock held. */
282                 ast_channel_unlock(chan);
283                 ast_bridge_lock(bridge);
284                 if (!native_data->detached) {
285                         if (f->subclass.integer == AST_CONTROL_HOLD) {
286                                 native_rtp_bridge_stop(bridge, chan);
287                         } else if ((f->subclass.integer == AST_CONTROL_UNHOLD) ||
288                                 (f->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) {
289                                 native_rtp_bridge_start(bridge, chan);
290                         }
291                 }
292                 ast_bridge_unlock(bridge);
293                 ast_channel_lock(chan);
294
295         }
296
297         return f;
298 }
299
300 /*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
301 static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
302 {
303         return (type == AST_FRAME_CONTROL ? 1 : 0);
304 }
305
306 /*! \brief Internal helper function which checks whether the channels are compatible with our native bridging */
307 static int native_rtp_bridge_capable(struct ast_channel *chan)
308 {
309         return !ast_channel_has_hook_requiring_audio(chan);
310 }
311
312 static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
313 {
314         enum ast_rtp_glue_result native_type;
315         struct ast_rtp_glue *glue0;
316         struct ast_rtp_glue *glue1;
317         RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
318         RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
319         RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
320         RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
321         RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup);
322         RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup);
323         int read_ptime0;
324         int read_ptime1;
325         int write_ptime0;
326         int write_ptime1;
327
328         if (!native_rtp_bridge_capable(bc0->chan)) {
329                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
330                         bridge->uniqueid, ast_channel_name(bc0->chan));
331                 return 0;
332         }
333
334         if (!native_rtp_bridge_capable(bc1->chan)) {
335                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
336                         bridge->uniqueid, ast_channel_name(bc1->chan));
337                 return 0;
338         }
339
340         native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1,
341                 &instance0, &instance1, &vinstance0, &vinstance1);
342         if (native_type == AST_RTP_GLUE_RESULT_FORBID) {
343                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
344                         bridge->uniqueid);
345                 return 0;
346         }
347
348         if (ao2_container_count(bc0->features->dtmf_hooks)
349                 && ast_rtp_instance_dtmf_mode_get(instance0)) {
350                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
351                         bridge->uniqueid, ast_channel_name(bc0->chan));
352                 return 0;
353         }
354
355         if (ao2_container_count(bc1->features->dtmf_hooks)
356                 && ast_rtp_instance_dtmf_mode_get(instance1)) {
357                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
358                         bridge->uniqueid, ast_channel_name(bc1->chan));
359                 return 0;
360         }
361
362         if (native_type == AST_RTP_GLUE_RESULT_LOCAL
363                 && (ast_rtp_instance_get_engine(instance0)->local_bridge
364                         != ast_rtp_instance_get_engine(instance1)->local_bridge
365                         || (ast_rtp_instance_get_engine(instance0)->dtmf_compatible
366                                 && !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(bc0->chan,
367                                         instance0, bc1->chan, instance1)))) {
368                 ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
369                         bridge->uniqueid);
370                 return 0;
371         }
372
373         cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
374         cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
375         if (!cap0 || !cap1) {
376                 return 0;
377         }
378
379         /* Make sure that codecs match */
380         if (glue0->get_codec) {
381                 glue0->get_codec(bc0->chan, cap0);
382         }
383         if (glue1->get_codec) {
384                 glue1->get_codec(bc1->chan, cap1);
385         }
386         if (ast_format_cap_count(cap0) != 0
387                 && ast_format_cap_count(cap1) != 0
388                 && !ast_format_cap_iscompatible(cap0, cap1)) {
389                 struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
390                 struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
391
392                 ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
393                         bridge->uniqueid,
394                         ast_format_cap_get_names(cap0, &codec_buf0),
395                         ast_format_cap_get_names(cap1, &codec_buf1));
396                 return 0;
397         }
398
399         read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan));
400         read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(bc1->chan));
401         write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(bc0->chan));
402         write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(bc1->chan));
403
404         if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
405                 ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
406                         bridge->uniqueid,
407                         read_ptime0, write_ptime1, read_ptime1, write_ptime0);
408                 return 0;
409         }
410
411         return 1;
412 }
413
414 static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
415 {
416         struct ast_bridge_channel *bc0;
417         struct ast_bridge_channel *bc1;
418         int is_compatible;
419
420         /* We require two channels before even considering native bridging */
421         if (bridge->num_channels != 2) {
422                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as two channels are required\n",
423                         bridge->uniqueid);
424                 return 0;
425         }
426
427         bc0 = AST_LIST_FIRST(&bridge->channels);
428         bc1 = AST_LIST_LAST(&bridge->channels);
429
430         ast_channel_lock_both(bc0->chan, bc1->chan);
431         is_compatible = native_rtp_bridge_compatible_check(bridge, bc0, bc1);
432         ast_channel_unlock(bc0->chan);
433         ast_channel_unlock(bc1->chan);
434
435         return is_compatible;
436 }
437
438 /*! \brief Helper function which adds frame hook to bridge channel */
439 static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
440 {
441         struct native_rtp_bridge_data *data = ao2_alloc(sizeof(*data), NULL);
442         static struct ast_framehook_interface hook = {
443                 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
444                 .event_cb = native_rtp_framehook,
445                 .destroy_cb = __ao2_cleanup,
446                 .consume_cb = native_rtp_framehook_consume,
447                 .disable_inheritance = 1,
448         };
449
450         if (!data) {
451                 return -1;
452         }
453
454         ast_channel_lock(bridge_channel->chan);
455         hook.data = ao2_bump(data);
456         data->id = ast_framehook_attach(bridge_channel->chan, &hook);
457         ast_channel_unlock(bridge_channel->chan);
458         if (data->id < 0) {
459                 /* We need to drop both the reference we hold, and the one the framehook would hold */
460                 ao2_ref(data, -2);
461                 return -1;
462         }
463
464         bridge_channel->tech_pvt = data;
465
466         return 0;
467 }
468
469 /*! \brief Helper function which removes frame hook from bridge channel */
470 static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
471 {
472         RAII_VAR(struct native_rtp_bridge_data *, data, bridge_channel->tech_pvt, ao2_cleanup);
473
474         if (!data) {
475                 return;
476         }
477
478         ast_channel_lock(bridge_channel->chan);
479         ast_framehook_detach(bridge_channel->chan, data->id);
480         data->detached = 1;
481         ast_channel_unlock(bridge_channel->chan);
482         bridge_channel->tech_pvt = NULL;
483 }
484
485 static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
486 {
487         native_rtp_bridge_framehook_detach(bridge_channel);
488         if (native_rtp_bridge_framehook_attach(bridge_channel)) {
489                 return -1;
490         }
491
492         native_rtp_bridge_start(bridge, NULL);
493         return 0;
494 }
495
496 static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
497 {
498         native_rtp_bridge_join(bridge, bridge_channel);
499 }
500
501 static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
502 {
503         native_rtp_bridge_framehook_detach(bridge_channel);
504         native_rtp_bridge_stop(bridge, NULL);
505 }
506
507 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
508 {
509         return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
510 }
511
512 static struct ast_bridge_technology native_rtp_bridge = {
513         .name = "native_rtp",
514         .capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
515         .preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
516         .join = native_rtp_bridge_join,
517         .unsuspend = native_rtp_bridge_unsuspend,
518         .leave = native_rtp_bridge_leave,
519         .suspend = native_rtp_bridge_leave,
520         .write = native_rtp_bridge_write,
521         .compatible = native_rtp_bridge_compatible,
522 };
523
524 static int unload_module(void)
525 {
526         ast_bridge_technology_unregister(&native_rtp_bridge);
527         return 0;
528 }
529
530 static int load_module(void)
531 {
532         if (ast_bridge_technology_register(&native_rtp_bridge)) {
533                 unload_module();
534                 return AST_MODULE_LOAD_DECLINE;
535         }
536         return AST_MODULE_LOAD_SUCCESS;
537 }
538
539 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Native RTP bridging module");