2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * Joshua Colp <jcolp@digium.com>
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.
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.
21 * \brief Native RTP bridging technology module
23 * \author Joshua Colp <jcolp@digium.com>
29 <support_level>core</support_level>
34 ASTERISK_REGISTER_FILE()
39 #include <sys/types.h>
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"
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 */
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)
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;
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;
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;
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;
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;
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;
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;
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;
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;
115 return AST_RTP_GLUE_RESULT_REMOTE;
121 * \brief Start native RTP bridging of two channels
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.
126 * \note Bridge must be locked when calling this function.
128 static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channel *target)
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);
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);
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);
155 if (ast_rtp_instance_get_engine(instance1)->local_bridge) {
156 ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, instance0);
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));
164 case AST_RTP_GLUE_RESULT_REMOTE:
165 if (glue0->get_codec) {
166 glue0->get_codec(bc0->chan, cap0);
168 if (glue1->get_codec) {
169 glue1->get_codec(bc1->chan, cap1);
172 /* If we have a target, it's the channel that received the UNHOLD or UPDATE_RTP_PEER frame and was told to resume */
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));
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
185 if (bc0->chan == target) {
186 glue0->update_peer(bc0->chan, instance1, vinstance1, tinstance1, cap1, 0);
188 glue1->update_peer(bc1->chan, instance0, vinstance0, tinstance0, cap0, 0);
192 case AST_RTP_GLUE_RESULT_FORBID:
196 ast_channel_unlock(bc0->chan);
197 ast_channel_unlock(bc1->chan);
200 static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
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);
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);
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);
223 if (instance1 && ast_rtp_instance_get_engine(instance1)->local_bridge) {
224 ast_rtp_instance_get_engine(instance1)->local_bridge(instance1, NULL);
226 ast_rtp_instance_set_bridged(instance0, NULL);
228 ast_rtp_instance_set_bridged(instance1, NULL);
231 case AST_RTP_GLUE_RESULT_REMOTE:
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.
237 if (bc0->chan == target) {
238 glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
240 glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
244 case AST_RTP_GLUE_RESULT_FORBID:
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);
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));
256 ast_channel_unlock(bc0->chan);
257 ast_channel_unlock(bc1->chan);
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)
263 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
265 if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
269 bridge = ast_channel_get_bridge(chan);
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 ast_channel_unlock(chan);
277 ast_bridge_lock(bridge);
278 if (f->subclass.integer == AST_CONTROL_HOLD) {
279 native_rtp_bridge_stop(bridge, chan);
280 } else if ((f->subclass.integer == AST_CONTROL_UNHOLD) || (f->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) {
281 native_rtp_bridge_start(bridge, chan);
283 ast_bridge_unlock(bridge);
284 ast_channel_lock(chan);
291 /*! \brief Callback function which informs upstream if we are consuming a frame of a specific type */
292 static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
294 return (type == AST_FRAME_CONTROL ? 1 : 0);
297 /*! \brief Internal helper function which checks whether the channels are compatible with our native bridging */
298 static int native_rtp_bridge_capable(struct ast_channel *chan)
300 return !ast_channel_has_hook_requiring_audio(chan);
303 static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
305 struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
306 struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
307 enum ast_rtp_glue_result native_type;
308 struct ast_rtp_glue *glue0, *glue1;
309 RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
310 RAII_VAR(struct ast_rtp_instance *, instance1, NULL, ao2_cleanup);
311 RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
312 RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
313 RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup);
314 RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup);
315 int read_ptime0, read_ptime1, write_ptime0, write_ptime1;
317 /* We require two channels before even considering native bridging */
318 if (bridge->num_channels != 2) {
319 ast_debug(1, "Bridge '%s' can not use native RTP bridge as two channels are required\n",
324 if (!native_rtp_bridge_capable(bc0->chan)) {
325 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
326 bridge->uniqueid, ast_channel_name(bc0->chan));
330 if (!native_rtp_bridge_capable(bc1->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(bc1->chan));
336 if ((native_type = native_rtp_bridge_get(bc0->chan, bc1->chan, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1))
337 == AST_RTP_GLUE_RESULT_FORBID) {
338 ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
343 if (ao2_container_count(bc0->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance0)) {
344 ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
345 bridge->uniqueid, ast_channel_name(bc0->chan));
349 if (ao2_container_count(bc1->features->dtmf_hooks) && ast_rtp_instance_dtmf_mode_get(instance1)) {
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(bc1->chan));
355 if ((native_type == AST_RTP_GLUE_RESULT_LOCAL) && ((ast_rtp_instance_get_engine(instance0)->local_bridge !=
356 ast_rtp_instance_get_engine(instance1)->local_bridge) ||
357 (ast_rtp_instance_get_engine(instance0)->dtmf_compatible &&
358 !ast_rtp_instance_get_engine(instance0)->dtmf_compatible(bc0->chan, instance0, bc1->chan, instance1)))) {
359 ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
364 cap0 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
365 cap1 = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
366 if (!cap0 || !cap1) {
370 /* Make sure that codecs match */
371 if (glue0->get_codec) {
372 glue0->get_codec(bc0->chan, cap0);
374 if (glue1->get_codec) {
375 glue1->get_codec(bc1->chan, cap1);
377 if (ast_format_cap_count(cap0) != 0 && ast_format_cap_count(cap1) != 0 && !ast_format_cap_iscompatible(cap0, cap1)) {
378 struct ast_str *codec_buf0 = ast_str_alloca(64);
379 struct ast_str *codec_buf1 = ast_str_alloca(64);
380 ast_debug(1, "Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
381 ast_format_cap_get_names(cap0, &codec_buf0), ast_format_cap_get_names(cap1, &codec_buf1));
385 read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan));
386 read_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawreadformat(bc1->chan));
387 write_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawwriteformat(bc0->chan));
388 write_ptime1 = ast_format_cap_get_format_framing(cap1, ast_channel_rawwriteformat(bc1->chan));
390 if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
391 ast_debug(1, "Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
392 read_ptime0, write_ptime1, read_ptime1, write_ptime0);
399 /*! \brief Helper function which adds frame hook to bridge channel */
400 static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
402 struct native_rtp_bridge_data *data = ao2_alloc(sizeof(*data), NULL);
403 static struct ast_framehook_interface hook = {
404 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
405 .event_cb = native_rtp_framehook,
406 .consume_cb = native_rtp_framehook_consume,
407 .disable_inheritance = 1,
414 ast_channel_lock(bridge_channel->chan);
415 data->id = ast_framehook_attach(bridge_channel->chan, &hook);
416 ast_channel_unlock(bridge_channel->chan);
422 bridge_channel->tech_pvt = data;
427 /*! \brief Helper function which removes frame hook from bridge channel */
428 static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
430 RAII_VAR(struct native_rtp_bridge_data *, data, bridge_channel->tech_pvt, ao2_cleanup);
436 ast_channel_lock(bridge_channel->chan);
437 ast_framehook_detach(bridge_channel->chan, data->id);
438 ast_channel_unlock(bridge_channel->chan);
439 bridge_channel->tech_pvt = NULL;
442 static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
444 native_rtp_bridge_framehook_detach(bridge_channel);
445 if (native_rtp_bridge_framehook_attach(bridge_channel)) {
449 native_rtp_bridge_start(bridge, NULL);
453 static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
455 native_rtp_bridge_join(bridge, bridge_channel);
458 static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
460 native_rtp_bridge_framehook_detach(bridge_channel);
461 native_rtp_bridge_stop(bridge, NULL);
464 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
466 return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
469 static struct ast_bridge_technology native_rtp_bridge = {
470 .name = "native_rtp",
471 .capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
472 .preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
473 .join = native_rtp_bridge_join,
474 .unsuspend = native_rtp_bridge_unsuspend,
475 .leave = native_rtp_bridge_leave,
476 .suspend = native_rtp_bridge_leave,
477 .write = native_rtp_bridge_write,
478 .compatible = native_rtp_bridge_compatible,
481 static int unload_module(void)
483 ast_bridge_technology_unregister(&native_rtp_bridge);
487 static int load_module(void)
489 if (ast_bridge_technology_register(&native_rtp_bridge)) {
491 return AST_MODULE_LOAD_DECLINE;
493 return AST_MODULE_LOAD_SUCCESS;
496 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Native RTP bridging module");