2362ad296dc1a8d2ad64c2d86f7c7e7ddf322089
[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 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41
42 #include "asterisk/module.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/bridge.h"
45 #include "asterisk/bridge_technology.h"
46 #include "asterisk/frame.h"
47 #include "asterisk/rtp_engine.h"
48
49 /*! \brief Internal structure which contains information about bridged RTP channels */
50 struct native_rtp_bridge_data {
51         /*! \brief Framehook used to intercept certain control frames */
52         int id;
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 *c0 = AST_LIST_FIRST(&bridge->channels);
131         struct ast_bridge_channel *c1 = 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_NOLOCK), ast_format_cap_destroy);
141         RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
142
143         if (c0 == c1) {
144                 return;
145         }
146
147         ast_channel_lock_both(c0->chan, c1->chan);
148         native_type = native_rtp_bridge_get(c0->chan, c1->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_debug(2, "Locally RTP bridged '%s' and '%s' in stack\n",
161                         ast_channel_name(c0->chan), ast_channel_name(c1->chan));
162                 break;
163
164         case AST_RTP_GLUE_RESULT_REMOTE:
165                 if (glue0->get_codec) {
166                         glue0->get_codec(c0->chan, cap0);
167                 }
168                 if (glue1->get_codec) {
169                         glue1->get_codec(c1->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(c0->chan, instance1, vinstance1, tinstance1, cap1, 0);
175                         glue1->update_peer(c1->chan, instance0, vinstance0, tinstance0, cap0, 0);
176                         ast_debug(2, "Remotely bridged '%s' and '%s' - media will flow directly between them\n",
177                                 ast_channel_name(c0->chan), ast_channel_name(c1->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 (c0->chan == target) {
186                                 glue0->update_peer(c0->chan, instance1, vinstance1, tinstance1, cap1, 0);
187                         } else {
188                                 glue1->update_peer(c1->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(c0->chan);
197         ast_channel_unlock(c1->chan);
198 }
199
200 static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
201 {
202         struct ast_bridge_channel *c0 = AST_LIST_FIRST(&bridge->channels);
203         struct ast_bridge_channel *c1 = 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 (c0 == c1) {
212                 return;
213         }
214
215         if (!c0 || !c1) {
216                 return;
217         }
218
219         ast_channel_lock_both(c0->chan, c1->chan);
220         native_type = native_rtp_bridge_get(c0->chan, c1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1);
221
222         switch (native_type) {
223         case AST_RTP_GLUE_RESULT_LOCAL:
224                 if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
225                         ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, NULL);
226                 }
227                 if (instance1 && ast_rtp_instance_get_engine(instance1)->local_bridge) {
228                         ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, NULL);
229                 }
230                 ast_rtp_instance_set_bridged(instance0, NULL);
231                 if (instance1) {
232                         ast_rtp_instance_set_bridged(instance1, NULL);
233                 }
234                 break;
235         case AST_RTP_GLUE_RESULT_REMOTE:
236                 if (!target) {
237                         if (ast_channel_is_leaving_bridge(c0->chan)) {
238                                 glue0->update_peer(c0->chan, NULL, NULL, NULL, NULL, 0);
239                         }
240                         if (glue1 && ast_channel_is_leaving_bridge(c1->chan)) {
241                                 glue1->update_peer(c1->chan, NULL, NULL, NULL, NULL, 0);
242                         }
243                 } else {
244                         /*
245                          * If a target was provided, it is being put on hold and should expect to
246                          * receive mediafrom sterisk instead of what it was previously connected to.
247                          */
248                         if (c0->chan == target) {
249                                 glue0->update_peer(c0->chan, NULL, NULL, NULL, NULL, 0);
250                         } else if (glue1) {
251                                 glue1->update_peer(c1->chan, NULL, NULL, NULL, NULL, 0);
252                         }
253                 }
254                 break;
255         case AST_RTP_GLUE_RESULT_FORBID:
256                 break;
257         }
258
259         ast_debug(2, "Discontinued RTP bridging of '%s' and '%s' - media will flow through Asterisk core\n",
260                 ast_channel_name(c0->chan), ast_channel_name(c1->chan));
261
262         ast_channel_unlock(c0->chan);
263         ast_channel_unlock(c1->chan);
264 }
265
266 /*! \brief Frame hook that is called to intercept hold/unhold */
267 static struct ast_frame *native_rtp_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
268 {
269         RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
270
271         if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
272                 return f;
273         }
274
275         bridge = ast_channel_get_bridge(chan);
276
277         if (bridge) {
278                 /* native_rtp_bridge_start/stop are not being called from bridging
279                    core so we need to lock the bridge prior to calling these functions
280                    Unfortunately that means unlocking the channel, but as it
281                    should not be modified this should be okay...hopefully */
282                 ast_channel_unlock(chan);
283                 ast_bridge_lock(bridge);
284                 if (f->subclass.integer == AST_CONTROL_HOLD) {
285                         native_rtp_bridge_stop(bridge, chan);
286                 } else if ((f->subclass.integer == AST_CONTROL_UNHOLD) || (f->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) {
287                         native_rtp_bridge_start(bridge, chan);
288                 }
289                 ast_bridge_unlock(bridge);
290                 ast_channel_lock(chan);
291
292         }
293
294         return f;
295 }
296
297 /*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
298 static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
299 {
300         return (type == AST_FRAME_CONTROL ? 1 : 0);
301 }
302
303 /*! \brief Internal helper function which checks whether the channels are compatible with our native bridging */
304 static int native_rtp_bridge_capable(struct ast_channel *chan)
305 {
306         return !ast_channel_has_hook_requiring_audio(chan);
307 }
308
309 static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
310 {
311         struct ast_bridge_channel *c0 = AST_LIST_FIRST(&bridge->channels);
312         struct ast_bridge_channel *c1 = AST_LIST_LAST(&bridge->channels);
313         enum ast_rtp_glue_result native_type;
314         struct ast_rtp_glue *glue0, *glue1;
315         RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
316         RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
317         RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
318         RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
319         RAII_VAR(struct ast_format_cap *, cap0, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
320         RAII_VAR(struct ast_format_cap *, cap1, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK), ast_format_cap_destroy);
321         int read_ptime0, read_ptime1, write_ptime0, write_ptime1;
322
323         /* We require two channels before even considering native bridging */
324         if (bridge->num_channels != 2) {
325                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as two channels are required\n",
326                         bridge->uniqueid);
327                 return 0;
328         }
329
330         if (!native_rtp_bridge_capable(c0->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(c0->chan));
333                 return 0;
334         }
335
336         if (!native_rtp_bridge_capable(c1->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(c1->chan));
339                 return 0;
340         }
341
342         if ((native_type = native_rtp_bridge_get(c0->chan, c1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1))
343                 == AST_RTP_GLUE_RESULT_FORBID) {
344                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
345                         bridge->uniqueid);
346                 return 0;
347         }
348
349         if (ao2_container_count(c0->features->dtmf_hooks) && 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(c0->chan));
352                 return 0;
353         }
354
355         if (ao2_container_count(c1->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance1)) {
356                 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
357                         bridge->uniqueid, ast_channel_name(c1->chan));
358                 return 0;
359         }
360
361         if ((native_type == AST_RTP_GLUE_RESULT_LOCAL) && ((ast_rtp_instance_get_engine(instance0)->local_bridge !=
362                 ast_rtp_instance_get_engine(instance1)->local_bridge) ||
363                 (ast_rtp_instance_get_engine(instance0)->dtmf_compatible &&
364                         !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(c0->chan, instance0, c1->chan, instance1)))) {
365                 ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
366                         bridge->uniqueid);
367                 return 0;
368         }
369
370         /* Make sure that codecs match */
371         if (glue0->get_codec) {
372                 glue0->get_codec(c0->chan, cap0);
373         }
374         if (glue1->get_codec) {
375                 glue1->get_codec(c1->chan, cap1);
376         }
377         if (!ast_format_cap_is_empty(cap0) && !ast_format_cap_is_empty(cap1) && !ast_format_cap_has_joint(cap0, cap1)) {
378                 char tmp0[256] = { 0, }, tmp1[256] = { 0, };
379
380                 ast_debug(1, "Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
381                         ast_getformatname_multiple(tmp0, sizeof(tmp0), cap0),
382                         ast_getformatname_multiple(tmp1, sizeof(tmp1), cap1));
383                 return 0;
384         }
385
386         read_ptime0 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance0)->pref, ast_channel_rawreadformat(c0->chan))).cur_ms;
387         read_ptime1 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance1)->pref, ast_channel_rawreadformat(c1->chan))).cur_ms;
388         write_ptime0 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance0)->pref, ast_channel_rawwriteformat(c0->chan))).cur_ms;
389         write_ptime1 = (ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance1)->pref, ast_channel_rawwriteformat(c1->chan))).cur_ms;
390
391         if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
392                 ast_debug(1, "Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
393                                 read_ptime0, write_ptime1, read_ptime1, write_ptime0);
394                 return 0;
395         }
396
397         return 1;
398 }
399
400 /*! \brief Helper function which adds frame hook to bridge channel */
401 static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
402 {
403         struct native_rtp_bridge_data *data = ao2_alloc(sizeof(*data), NULL);
404         static struct ast_framehook_interface hook = {
405                 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
406                 .event_cb = native_rtp_framehook,
407                 .consume_cb = native_rtp_framehook_consume,
408                 .disable_inheritance = 1,
409         };
410
411         if (!data) {
412                 return -1;
413         }
414
415         ast_channel_lock(bridge_channel->chan);
416         data->id = ast_framehook_attach(bridge_channel->chan, &hook);
417         ast_channel_unlock(bridge_channel->chan);
418         if (data->id < 0) {
419                 ao2_cleanup(data);
420                 return -1;
421         }
422
423         bridge_channel->tech_pvt = data;
424
425         return 0;
426 }
427
428 /*! \brief Helper function which removes frame hook from bridge channel */
429 static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
430 {
431         RAII_VAR(struct native_rtp_bridge_data *, data, bridge_channel->tech_pvt, ao2_cleanup);
432
433         if (!data) {
434                 return;
435         }
436
437         ast_channel_lock(bridge_channel->chan);
438         ast_framehook_detach(bridge_channel->chan, data->id);
439         ast_channel_unlock(bridge_channel->chan);
440         bridge_channel->tech_pvt = NULL;
441 }
442
443 static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
444 {
445         native_rtp_bridge_framehook_detach(bridge_channel);
446         if (native_rtp_bridge_framehook_attach(bridge_channel)) {
447                 return -1;
448         }
449
450         native_rtp_bridge_start(bridge, NULL);
451         return 0;
452 }
453
454 static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
455 {
456         native_rtp_bridge_join(bridge, bridge_channel);
457 }
458
459 static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
460 {
461         struct ast_rtp_glue *glue;
462         RAII_VAR(struct ast_rtp_instance *, instance, NULL, ao2_cleanup);
463         RAII_VAR(struct ast_rtp_instance *, vinstance, NULL, ao2_cleanup);
464         RAII_VAR(struct ast_rtp_instance *, tinstance, NULL, ao2_cleanup);
465
466         native_rtp_bridge_framehook_detach(bridge_channel);
467
468         glue = ast_rtp_instance_get_glue(ast_channel_tech(bridge_channel->chan)->type);
469         if (!glue) {
470                 return;
471         }
472
473         glue->get_rtp_info(bridge_channel->chan, &instance);
474
475         if (glue->get_vrtp_info) {
476                 glue->get_vrtp_info(bridge_channel->chan, &vinstance);
477         }
478
479         if (glue->get_trtp_info) {
480                 glue->get_trtp_info(bridge_channel->chan, &tinstance);
481         }
482
483         /* Tear down P2P bridges */
484         if (instance) {
485                 ast_rtp_instance_set_bridged(instance, NULL);
486         }
487         if (vinstance) {
488                 ast_rtp_instance_set_bridged(vinstance, NULL);
489         }
490         if (tinstance) {
491                 ast_rtp_instance_set_bridged(tinstance, NULL);
492         }
493
494         if (ast_channel_is_leaving_bridge(bridge_channel->chan)) {
495                 /* Direct RTP may have occurred, tear it down */
496                 glue->update_peer(bridge_channel->chan, NULL, NULL, NULL, NULL, 0);
497         }
498
499         native_rtp_bridge_stop(bridge, NULL);
500 }
501
502 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
503 {
504         return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
505 }
506
507 static struct ast_bridge_technology native_rtp_bridge = {
508         .name = "native_rtp",
509         .capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
510         .preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
511         .join = native_rtp_bridge_join,
512         .unsuspend = native_rtp_bridge_unsuspend,
513         .leave = native_rtp_bridge_leave,
514         .suspend = native_rtp_bridge_leave,
515         .write = native_rtp_bridge_write,
516         .compatible = native_rtp_bridge_compatible,
517 };
518
519 static int unload_module(void)
520 {
521         ast_format_cap_destroy(native_rtp_bridge.format_capabilities);
522         return ast_bridge_technology_unregister(&native_rtp_bridge);
523 }
524
525 static int load_module(void)
526 {
527         if (!(native_rtp_bridge.format_capabilities = ast_format_cap_alloc(0))) {
528                 return AST_MODULE_LOAD_DECLINE;
529         }
530         ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_AUDIO);
531         ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_VIDEO);
532         ast_format_cap_add_all_by_type(native_rtp_bridge.format_capabilities, AST_FORMAT_TYPE_TEXT);
533
534         return ast_bridge_technology_register(&native_rtp_bridge);
535 }
536
537 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Native RTP bridging module");