Asterisk - The Open Source Telephony Project  18.5.0
bridge_native_rtp.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Joshua Colp <[email protected]>
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 <[email protected]>
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"
44 #include "asterisk/frame.h"
45 #include "asterisk/rtp_engine.h"
46 #include "asterisk/stream.h"
47 
48 /*! \brief Internal structure which contains bridged RTP channel hook data */
50  /*! \brief Framehook used to intercept certain control frames */
51  int id;
52  /*! \brief Set when this framehook has been detached */
53  unsigned int detached;
54 };
55 
57  /*! \brief RTP instance */
59  /*! \brief glue result */
61 };
62 
63 struct rtp_glue_data {
64  /*!
65  * \brief glue callbacks
66  *
67  * \note The glue data is considered valid if cb is not NULL.
68  */
69  struct ast_rtp_glue *cb;
70  struct rtp_glue_stream audio;
71  struct rtp_glue_stream video;
72  /*! Combined glue result of both bridge channels. */
74 };
75 
76 /*! \brief Internal structure which contains instance information about bridged RTP channels */
78  /*! \brief Channel's hook data */
80  /*!
81  * \brief Glue callbacks to bring remote channel streams back to Asterisk.
82  * \note NULL if channel streams are local.
83  */
85  /*! \brief Channel's cached RTP glue information */
86  struct rtp_glue_data glue;
87 };
88 
89 /*! \brief Forward declarations */
90 static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
91 static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
92 static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
93 static void native_rtp_bridge_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
94 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
95 static int native_rtp_bridge_compatible(struct ast_bridge *bridge);
96 static void native_rtp_stream_topology_changed(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
97 
99  .name = "native_rtp",
100  .capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
101  .preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
102  .join = native_rtp_bridge_join,
103  .unsuspend = native_rtp_bridge_unsuspend,
104  .leave = native_rtp_bridge_leave,
105  .suspend = native_rtp_bridge_suspend,
106  .write = native_rtp_bridge_write,
107  .compatible = native_rtp_bridge_compatible,
108  .stream_topology_changed = native_rtp_stream_topology_changed,
109 };
110 
111 static void rtp_glue_data_init(struct rtp_glue_data *glue)
112 {
113  glue->cb = NULL;
114  glue->audio.instance = NULL;
116  glue->video.instance = NULL;
119 }
120 
121 static void rtp_glue_data_destroy(struct rtp_glue_data *glue)
122 {
123  if (!glue) {
124  return;
125  }
126  ao2_cleanup(glue->audio.instance);
127  ao2_cleanup(glue->video.instance);
128 }
129 
130 static void rtp_glue_data_reset(struct rtp_glue_data *glue)
131 {
132  rtp_glue_data_destroy(glue);
133  rtp_glue_data_init(glue);
134 }
135 
137 {
138  ast_debug(2, "Destroying channel tech_pvt data %p\n", data);
139 
140  /*
141  * hook_data will probably already have been unreferenced by the framehook detach
142  * and the pointer set to null.
143  */
144  ao2_cleanup(data->hook_data);
145 
146  rtp_glue_data_reset(&data->glue);
147  ast_free(data);
148 }
149 
151 {
152  struct native_rtp_bridge_channel_data *data;
153 
154  data = ast_calloc(1, sizeof(*data));
155  if (data) {
156  rtp_glue_data_init(&data->glue);
157  }
158  return data;
159 }
160 
161 /*!
162  * \internal
163  * \brief Helper function which gets all RTP information (glue and instances) relating to the given channels
164  *
165  * \retval 0 on success.
166  * \retval -1 on error.
167  */
168 static int rtp_glue_data_get(struct ast_channel *c0, struct rtp_glue_data *glue0,
169  struct ast_channel *c1, struct rtp_glue_data *glue1)
170 {
171  struct ast_rtp_glue *cb0;
172  struct ast_rtp_glue *cb1;
173  enum ast_rtp_glue_result combined_result;
174 
177  if (!cb0 || !cb1) {
178  /* One or both channels doesn't have any RTP glue registered. */
179  return -1;
180  }
181 
182  /* The glue callbacks bump the RTP instance refcounts for us. */
183 
184  glue0->cb = cb0;
185  glue0->audio.result = cb0->get_rtp_info(c0, &glue0->audio.instance);
186  glue0->video.result = cb0->get_vrtp_info
188 
189  glue1->cb = cb1;
190  glue1->audio.result = cb1->get_rtp_info(c1, &glue1->audio.instance);
191  glue1->video.result = cb1->get_vrtp_info
193 
194  /*
195  * Now determine the combined glue result.
196  */
197 
198  /* Apply any limitations on direct media bridging that may be present */
199  if (glue0->audio.result == glue1->audio.result && glue1->audio.result == AST_RTP_GLUE_RESULT_REMOTE) {
200  if (glue0->cb->allow_rtp_remote && !glue0->cb->allow_rtp_remote(c0, glue1->audio.instance)) {
201  /* If the allow_rtp_remote indicates that remote isn't allowed, revert to local bridge */
203  } else if (glue1->cb->allow_rtp_remote && !glue1->cb->allow_rtp_remote(c1, glue0->audio.instance)) {
205  }
206  }
207  if (glue0->video.result == glue1->video.result && glue1->video.result == AST_RTP_GLUE_RESULT_REMOTE) {
208  if (glue0->cb->allow_vrtp_remote && !glue0->cb->allow_vrtp_remote(c0, glue1->video.instance)) {
209  /* If the allow_vrtp_remote indicates that remote isn't allowed, revert to local bridge */
211  } else if (glue1->cb->allow_vrtp_remote && !glue1->cb->allow_vrtp_remote(c1, glue0->video.instance)) {
213  }
214  }
215 
216  /* If we are carrying video, and both sides are not going to remotely bridge... fail the native bridge */
219  || glue0->video.result != AST_RTP_GLUE_RESULT_REMOTE)) {
221  }
224  || glue1->video.result != AST_RTP_GLUE_RESULT_REMOTE)) {
226  }
227 
228  /* The order of preference is: forbid, local, and remote. */
230  || glue1->audio.result == AST_RTP_GLUE_RESULT_FORBID) {
231  /* If any sort of bridge is forbidden just completely bail out and go back to generic bridging */
232  combined_result = AST_RTP_GLUE_RESULT_FORBID;
233  } else if (glue0->audio.result == AST_RTP_GLUE_RESULT_LOCAL
234  || glue1->audio.result == AST_RTP_GLUE_RESULT_LOCAL) {
235  combined_result = AST_RTP_GLUE_RESULT_LOCAL;
236  } else {
237  combined_result = AST_RTP_GLUE_RESULT_REMOTE;
238  }
239  glue0->result = combined_result;
240  glue1->result = combined_result;
241 
242  return 0;
243 }
244 
245 /*!
246  * \internal
247  * \brief Get the current RTP native bridge combined glue result.
248  * \since 15.0.0
249  *
250  * \param c0 First bridge channel
251  * \param c1 Second bridge channel
252  *
253  * \note Both channels must be locked when calling this function.
254  *
255  * \return Current combined glue result.
256  */
258  struct ast_channel *c1)
259 {
260  struct rtp_glue_data glue_a;
261  struct rtp_glue_data glue_b;
262  struct rtp_glue_data *glue0;
263  struct rtp_glue_data *glue1;
264  enum ast_rtp_glue_result combined_result;
265 
266  rtp_glue_data_init(&glue_a);
267  glue0 = &glue_a;
268  rtp_glue_data_init(&glue_b);
269  glue1 = &glue_b;
270  if (rtp_glue_data_get(c0, glue0, c1, glue1)) {
272  }
273 
274  combined_result = glue0->result;
275  rtp_glue_data_destroy(glue0);
276  rtp_glue_data_destroy(glue1);
277  return combined_result;
278 }
279 
280 /*!
281  * \internal
282  * \brief Start native RTP bridging of two channels
283  *
284  * \param bridge The bridge that had native RTP bridging happening on it
285  * \param target If remote RTP bridging, the channel that is unheld.
286  *
287  * \note Bridge must be locked when calling this function.
288  */
289 static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channel *target)
290 {
291  struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
292  struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
293  struct native_rtp_bridge_channel_data *data0;
294  struct native_rtp_bridge_channel_data *data1;
295  struct rtp_glue_data *glue0;
296  struct rtp_glue_data *glue1;
297  struct ast_format_cap *cap0;
298  struct ast_format_cap *cap1;
299  enum ast_rtp_glue_result native_type;
300 
301  if (bc0 == bc1) {
302  return;
303  }
304  data0 = bc0->tech_pvt;
305  data1 = bc1->tech_pvt;
306  if (!data0 || !data1) {
307  /* Not all channels are joined with the bridge tech yet */
308  return;
309  }
310  glue0 = &data0->glue;
311  glue1 = &data1->glue;
312 
313  ast_channel_lock_both(bc0->chan, bc1->chan);
314 
315  if (!glue0->cb || !glue1->cb) {
316  /*
317  * Somebody doesn't have glue data so the bridge isn't running
318  *
319  * Actually neither side should have glue data.
320  */
321  ast_assert(!glue0->cb && !glue1->cb);
322 
323  if (rtp_glue_data_get(bc0->chan, glue0, bc1->chan, glue1)) {
324  /*
325  * This might happen if one of the channels got masqueraded
326  * at a critical time. It's a bit of a stretch even then
327  * since the channel is in a bridge.
328  */
329  goto done;
330  }
331  }
332 
333  ast_debug(2, "Bridge '%s'. Tech starting '%s' and '%s' with target '%s'\n",
334  bridge->uniqueid, ast_channel_name(bc0->chan), ast_channel_name(bc1->chan),
335  target ? ast_channel_name(target) : "none");
336 
337  native_type = glue0->result;
338 
339  switch (native_type) {
343  }
346  }
349  ast_verb(4, "Locally RTP bridged '%s' and '%s' in stack\n",
351  break;
355  if (!cap0 || !cap1) {
356  ao2_cleanup(cap0);
357  ao2_cleanup(cap1);
358  break;
359  }
360 
361  if (glue0->cb->get_codec) {
362  glue0->cb->get_codec(bc0->chan, cap0);
363  }
364  if (glue1->cb->get_codec) {
365  glue1->cb->get_codec(bc1->chan, cap1);
366  }
367 
368  /*
369  * If we have a target, it's the channel that received the UNHOLD or
370  * UPDATE_RTP_PEER frame and was told to resume
371  */
372  if (!target) {
373  /* Send both channels to remote */
374  data0->remote_cb = glue0->cb;
375  data1->remote_cb = glue1->cb;
376  glue0->cb->update_peer(bc0->chan, glue1->audio.instance, glue1->video.instance, NULL, cap1, 0);
377  glue1->cb->update_peer(bc1->chan, glue0->audio.instance, glue0->video.instance, NULL, cap0, 0);
378  ast_verb(4, "Remotely bridged '%s' and '%s' - media will flow directly between them\n",
380  } else {
381  /*
382  * If a target was provided, it is the recipient of an unhold or an update and needs to have
383  * its media redirected to fit the current remote bridging needs. The other channel is either
384  * already set up to handle the new media path or will have its own set of updates independent
385  * of this pass.
386  */
387  ast_debug(2, "Bridge '%s'. Sending '%s' back to remote\n",
388  bridge->uniqueid, ast_channel_name(target));
389  if (bc0->chan == target) {
390  data0->remote_cb = glue0->cb;
391  glue0->cb->update_peer(bc0->chan, glue1->audio.instance, glue1->video.instance, NULL, cap1, 0);
392  } else {
393  data1->remote_cb = glue1->cb;
394  glue1->cb->update_peer(bc1->chan, glue0->audio.instance, glue0->video.instance, NULL, cap0, 0);
395  }
396  }
397 
398  ao2_cleanup(cap0);
399  ao2_cleanup(cap1);
400  break;
402  break;
403  }
404 
405  if (native_type != AST_RTP_GLUE_RESULT_REMOTE) {
406  /* Bring any remaining channels back to us. */
407  if (data0->remote_cb) {
408  ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
409  bridge->uniqueid, ast_channel_name(bc0->chan));
410  data0->remote_cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
411  data0->remote_cb = NULL;
412  }
413  if (data1->remote_cb) {
414  ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
415  bridge->uniqueid, ast_channel_name(bc1->chan));
416  data1->remote_cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
417  data1->remote_cb = NULL;
418  }
419  }
420 
421 done:
422  ast_channel_unlock(bc0->chan);
423  ast_channel_unlock(bc1->chan);
424 }
425 
426 /*!
427  * \internal
428  * \brief Stop native RTP bridging of two channels
429  *
430  * \param bridge The bridge that had native RTP bridging happening on it
431  * \param target If remote RTP bridging, the channel that is held.
432  *
433  * \note The first channel to leave the bridge triggers the cleanup for both channels
434  */
435 static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
436 {
437  struct ast_bridge_channel *bc0 = AST_LIST_FIRST(&bridge->channels);
438  struct ast_bridge_channel *bc1 = AST_LIST_LAST(&bridge->channels);
439  struct native_rtp_bridge_channel_data *data0;
440  struct native_rtp_bridge_channel_data *data1;
441  struct rtp_glue_data *glue0;
442  struct rtp_glue_data *glue1;
443 
444  if (bc0 == bc1) {
445  return;
446  }
447  data0 = bc0->tech_pvt;
448  data1 = bc1->tech_pvt;
449  if (!data0 || !data1) {
450  /* Not all channels are joined with the bridge tech */
451  return;
452  }
453  glue0 = &data0->glue;
454  glue1 = &data1->glue;
455 
456  ast_debug(2, "Bridge '%s'. Tech stopping '%s' and '%s' with target '%s'\n",
457  bridge->uniqueid, ast_channel_name(bc0->chan), ast_channel_name(bc1->chan),
458  target ? ast_channel_name(target) : "none");
459 
460  if (!glue0->cb || !glue1->cb) {
461  /*
462  * Somebody doesn't have glue data so the bridge isn't running
463  *
464  * Actually neither side should have glue data.
465  */
466  ast_assert(!glue0->cb && !glue1->cb);
467  /* At most one channel can be left at the remote endpoint here. */
468  ast_assert(!data0->remote_cb || !data1->remote_cb);
469 
470  /* Bring selected channel streams back to us */
471  if (data0->remote_cb && (!target || target == bc0->chan)) {
472  ast_channel_lock(bc0->chan);
473  ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
474  bridge->uniqueid, ast_channel_name(bc0->chan));
475  data0->remote_cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
476  data0->remote_cb = NULL;
477  ast_channel_unlock(bc0->chan);
478  }
479  if (data1->remote_cb && (!target || target == bc1->chan)) {
480  ast_channel_lock(bc1->chan);
481  ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
482  bridge->uniqueid, ast_channel_name(bc1->chan));
483  data1->remote_cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
484  data1->remote_cb = NULL;
485  ast_channel_unlock(bc1->chan);
486  }
487  return;
488  }
489 
490  ast_channel_lock_both(bc0->chan, bc1->chan);
491 
492  switch (glue0->result) {
496  }
499  }
502  break;
504  if (target) {
505  /*
506  * If a target was provided, it is being put on hold and should expect to
507  * receive media from Asterisk instead of what it was previously connected to.
508  */
509  ast_debug(2, "Bridge '%s'. Bringing back '%s' to us\n",
510  bridge->uniqueid, ast_channel_name(target));
511  if (bc0->chan == target) {
512  data0->remote_cb = NULL;
513  glue0->cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
514  } else {
515  data1->remote_cb = NULL;
516  glue1->cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
517  }
518  } else {
519  data0->remote_cb = NULL;
520  data1->remote_cb = NULL;
521  /*
522  * XXX We don't want to bring back the channels if we are
523  * switching to T.38. We have received a reinvite on one channel
524  * and we will be sending a reinvite on the other to start T.38.
525  * If we bring the streams back now we confuse the chan_pjsip
526  * channel driver processing the incoming T.38 reinvite with
527  * reinvite glare. I think this is really a bug in chan_pjsip
528  * that this exception case is working around.
529  */
532  ast_debug(2, "Bridge '%s'. Bringing back '%s' and '%s' to us\n",
533  bridge->uniqueid, ast_channel_name(bc0->chan),
534  ast_channel_name(bc1->chan));
535  glue0->cb->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
536  glue1->cb->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
537  } else {
538  ast_debug(2, "Bridge '%s'. Skip bringing back '%s' and '%s' to us\n",
539  bridge->uniqueid, ast_channel_name(bc0->chan),
540  ast_channel_name(bc1->chan));
541  }
542  }
543  break;
545  break;
546  }
547 
548  rtp_glue_data_reset(glue0);
549  rtp_glue_data_reset(glue1);
550 
551  ast_debug(2, "Discontinued RTP bridging of '%s' and '%s' - media will flow through Asterisk core\n",
553 
554  ast_channel_unlock(bc0->chan);
555  ast_channel_unlock(bc1->chan);
556 }
557 
558 /*!
559  * \internal
560  * \brief Frame hook that is called to intercept hold/unhold
561  */
562 static struct ast_frame *native_rtp_framehook(struct ast_channel *chan,
563  struct ast_frame *f, enum ast_framehook_event event, void *data)
564 {
565  struct ast_bridge *bridge;
566  struct native_rtp_framehook_data *native_data = data;
567 
568  if (!f
570  || event != AST_FRAMEHOOK_EVENT_WRITE) {
571  return f;
572  }
573 
574  bridge = ast_channel_get_bridge(chan);
575  if (bridge) {
576  /* native_rtp_bridge_start/stop are not being called from bridging
577  core so we need to lock the bridge prior to calling these functions
578  Unfortunately that means unlocking the channel, but as it
579  should not be modified this should be okay... hopefully...
580  unless this channel is being moved around right now and is in
581  the process of having this framehook removed (which is fine). To
582  ensure we then don't stop or start when we shouldn't we consult
583  the data provided. If this framehook has been detached then the
584  detached variable will be set. This is safe to check as it is only
585  manipulated with the bridge lock held. */
586  ast_channel_unlock(chan);
587  ast_bridge_lock(bridge);
588  if (!native_data->detached) {
589  switch (f->subclass.integer) {
590  case AST_CONTROL_HOLD:
591  native_rtp_bridge_stop(bridge, chan);
592  break;
593  case AST_CONTROL_UNHOLD:
595  native_rtp_bridge_start(bridge, chan);
596  break;
597  default:
598  break;
599  }
600  }
601  ast_bridge_unlock(bridge);
602  ao2_ref(bridge, -1);
603  ast_channel_lock(chan);
604  }
605 
606  return f;
607 }
608 
609 /*!
610  * \internal
611  * \brief Callback function which informs upstream if we are consuming a frame of a specific type
612  */
614 {
615  return (type == AST_FRAME_CONTROL ? 1 : 0);
616 }
617 
618 /*!
619  * \internal
620  * \brief Internal helper function which checks whether a channel is compatible with our native bridging
621  */
622 static int native_rtp_bridge_capable(struct ast_channel *chan)
623 {
625  && ast_channel_state(chan) == AST_STATE_UP;
626 }
627 
628 /*!
629  * \internal
630  * \brief Internal helper function which checks whether both channels are compatible with our native bridging
631  */
632 static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
633 {
634  enum ast_rtp_glue_result native_type;
635  int read_ptime0;
636  int read_ptime1;
637  int write_ptime0;
638  int write_ptime1;
639  struct rtp_glue_data glue_a;
640  struct rtp_glue_data glue_b;
641  RAII_VAR(struct ast_format_cap *, cap0, NULL, ao2_cleanup);
642  RAII_VAR(struct ast_format_cap *, cap1, NULL, ao2_cleanup);
645 
646  ast_debug(1, "Bridge '%s'. Checking compatability for channels '%s' and '%s'\n",
647  bridge->uniqueid, ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));
648 
649  if (!native_rtp_bridge_capable(bc0->chan)) {
650  ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
651  bridge->uniqueid, ast_channel_name(bc0->chan));
652  return 0;
653  }
654 
655  if (!native_rtp_bridge_capable(bc1->chan)) {
656  ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has features which prevent it\n",
657  bridge->uniqueid, ast_channel_name(bc1->chan));
658  return 0;
659  }
660 
661  rtp_glue_data_init(&glue_a);
662  glue0 = &glue_a;
663  rtp_glue_data_init(&glue_b);
664  glue1 = &glue_b;
665  if (rtp_glue_data_get(bc0->chan, glue0, bc1->chan, glue1)) {
666  ast_debug(1, "Bridge '%s' can not use native RTP bridge as could not get details\n",
667  bridge->uniqueid);
668  return 0;
669  }
670  native_type = glue0->result;
671 
672  if (native_type == AST_RTP_GLUE_RESULT_FORBID) {
673  ast_debug(1, "Bridge '%s' can not use native RTP bridge as it was forbidden while getting details\n",
674  bridge->uniqueid);
675  return 0;
676  }
677 
679  && ast_rtp_instance_dtmf_mode_get(glue0->audio.instance)) {
680  ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
681  bridge->uniqueid, ast_channel_name(bc0->chan));
682  return 0;
683  }
684 
686  && ast_rtp_instance_dtmf_mode_get(glue1->audio.instance)) {
687  ast_debug(1, "Bridge '%s' can not use native RTP bridge as channel '%s' has DTMF hooks\n",
688  bridge->uniqueid, ast_channel_name(bc1->chan));
689  return 0;
690  }
691 
692  if (native_type == AST_RTP_GLUE_RESULT_LOCAL
693  && (ast_rtp_instance_get_engine(glue0->audio.instance)->local_bridge
694  != ast_rtp_instance_get_engine(glue1->audio.instance)->local_bridge
695  || (ast_rtp_instance_get_engine(glue0->audio.instance)->dtmf_compatible
696  && !ast_rtp_instance_get_engine(glue0->audio.instance)->dtmf_compatible(bc0->chan,
697  glue0->audio.instance, bc1->chan, glue1->audio.instance)))) {
698  ast_debug(1, "Bridge '%s' can not use local native RTP bridge as local bridge or DTMF is not compatible\n",
699  bridge->uniqueid);
700  return 0;
701  }
702 
705  if (!cap0 || !cap1) {
706  return 0;
707  }
708 
709  /* Make sure that codecs match */
710  if (glue0->cb->get_codec) {
711  glue0->cb->get_codec(bc0->chan, cap0);
712  }
713  if (glue1->cb->get_codec) {
714  glue1->cb->get_codec(bc1->chan, cap1);
715  }
716  if (ast_format_cap_count(cap0) != 0
717  && ast_format_cap_count(cap1) != 0
718  && !ast_format_cap_iscompatible(cap0, cap1)) {
719  struct ast_str *codec_buf0 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
720  struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
721 
722  ast_debug(1, "Bridge '%s': Channel codec0 = %s is not codec1 = %s, cannot native bridge in RTP.\n",
723  bridge->uniqueid,
724  ast_format_cap_get_names(cap0, &codec_buf0),
725  ast_format_cap_get_names(cap1, &codec_buf1));
726  return 0;
727  }
728 
729  if (glue0->audio.instance && glue1->audio.instance) {
730  unsigned int framing_inst0, framing_inst1;
731  framing_inst0 = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(glue0->audio.instance));
732  framing_inst1 = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(glue1->audio.instance));
733  if (framing_inst0 != framing_inst1) {
734  /* ptimes are asymmetric on the two call legs so we can't use the native bridge */
735  ast_debug(1, "Asymmetric ptimes on the two call legs (%u != %u). Cannot native bridge in RTP\n",
736  framing_inst0, framing_inst1);
737  return 0;
738  }
739  ast_debug(3, "Symmetric ptimes on the two call legs (%u). May be able to native bridge in RTP\n",
740  framing_inst0);
741  }
742 
747 
748  if (read_ptime0 != write_ptime1 || read_ptime1 != write_ptime0) {
749  ast_debug(1, "Bridge '%s': Packetization differs between RTP streams (%d != %d or %d != %d). Cannot native bridge in RTP\n",
750  bridge->uniqueid,
751  read_ptime0, write_ptime1, read_ptime1, write_ptime0);
752  return 0;
753  }
754  ast_debug(3, "Bridge '%s': Packetization comparison success between RTP streams (read_ptime0:%d == write_ptime1:%d and read_ptime1:%d == write_ptime0:%d).\n",
755  bridge->uniqueid,
756  read_ptime0, write_ptime1, read_ptime1, write_ptime0);
757 
758  return 1;
759 }
760 
761 /*!
762  * \internal
763  * \brief Called by the bridge core "compatible' callback
764  */
765 static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
766 {
767  struct ast_bridge_channel *bc0;
768  struct ast_bridge_channel *bc1;
769  int is_compatible;
770 
771  /* We require two channels before even considering native bridging */
772  if (bridge->num_channels != 2) {
773  ast_debug(1, "Bridge '%s' can not use native RTP bridge as two channels are required\n",
774  bridge->uniqueid);
775  return 0;
776  }
777 
778  bc0 = AST_LIST_FIRST(&bridge->channels);
779  bc1 = AST_LIST_LAST(&bridge->channels);
780 
781  ast_channel_lock_both(bc0->chan, bc1->chan);
782  is_compatible = native_rtp_bridge_compatible_check(bridge, bc0, bc1);
783  ast_channel_unlock(bc0->chan);
784  ast_channel_unlock(bc1->chan);
785 
786  return is_compatible;
787 }
788 
789 /*!
790  * \internal
791  * \brief Helper function which adds frame hook to bridge channel
792  */
793 static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
794 {
795  struct native_rtp_bridge_channel_data *data = bridge_channel->tech_pvt;
796  struct ast_framehook_interface hook = {
798  .event_cb = native_rtp_framehook,
799  .destroy_cb = __ao2_cleanup,
800  .consume_cb = native_rtp_framehook_consume,
801  .disable_inheritance = 1,
802  };
803 
804  ast_assert(data->hook_data == NULL);
805  data->hook_data = ao2_alloc_options(sizeof(*data->hook_data), NULL,
807  if (!data->hook_data) {
808  return -1;
809  }
810 
811  ast_debug(2, "Bridge '%s'. Attaching hook data %p to '%s'\n",
812  bridge_channel->bridge->uniqueid, data, ast_channel_name(bridge_channel->chan));
813 
814  /* We're giving 1 ref to the framehook and keeping the one from the alloc for ourselves */
815  hook.data = ao2_bump(data->hook_data);
816 
817  ast_channel_lock(bridge_channel->chan);
818  data->hook_data->id = ast_framehook_attach(bridge_channel->chan, &hook);
819  ast_channel_unlock(bridge_channel->chan);
820  if (data->hook_data->id < 0) {
821  /*
822  * We need to drop both the reference we hold in data,
823  * and the one the framehook would hold.
824  */
825  ao2_ref(data->hook_data, -2);
826  data->hook_data = NULL;
827 
828  return -1;
829  }
830 
831  return 0;
832 }
833 
834 /*!
835  * \internal
836  * \brief Helper function which removes frame hook from bridge channel
837  */
838 static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
839 {
840  struct native_rtp_bridge_channel_data *data = bridge_channel->tech_pvt;
841 
842  if (!data || !data->hook_data) {
843  return;
844  }
845 
846  ast_debug(2, "Bridge '%s'. Detaching hook data %p from '%s'\n",
847  bridge_channel->bridge->uniqueid, data->hook_data, ast_channel_name(bridge_channel->chan));
848 
849  ast_channel_lock(bridge_channel->chan);
850  ast_framehook_detach(bridge_channel->chan, data->hook_data->id);
851  data->hook_data->detached = 1;
852  ast_channel_unlock(bridge_channel->chan);
853  ao2_cleanup(data->hook_data);
854  data->hook_data = NULL;
855 }
856 
858  struct ast_stream_topology *existing_topology,
859  struct ast_stream_topology *requested_topology)
860 {
861  struct ast_stream *stream;
862  const struct ast_format_cap *audio_formats = NULL;
863  struct ast_stream_topology *new_topology;
864  int i;
865 
866  new_topology = ast_stream_topology_clone(requested_topology);
867  if (!new_topology) {
868  return NULL;
869  }
870 
871  /* We find an existing stream with negotiated audio formats that we can place into
872  * any audio streams in the new topology to ensure that negotiation succeeds. Some
873  * endpoints incorrectly terminate the call if SDP negotiation fails.
874  */
875  for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
876  stream = ast_stream_topology_get_stream(existing_topology, i);
877 
878  if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
880  continue;
881  }
882 
883  audio_formats = ast_stream_get_formats(stream);
884  break;
885  }
886 
887  if (audio_formats) {
888  for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
889  stream = ast_stream_topology_get_stream(new_topology, i);
890 
891  if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
893  continue;
894  }
895 
896  /* We haven't actually modified audio_formats so this is safe */
897  ast_stream_set_formats(stream, (struct ast_format_cap *)audio_formats);
898  }
899  }
900 
901  for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
902  stream = ast_stream_topology_get_stream(new_topology, i);
903 
904  /* For both recvonly and sendonly the stream state reflects our state, that is we
905  * are receiving only and we are sending only. Since we are renegotiating a remote
906  * party we need to swap this to reflect what we will be doing. That is, if we are
907  * receiving from Alice then we want to be sending to Bob, so swap recvonly to
908  * sendonly.
909  */
912  } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
914  }
915  }
916 
917  return new_topology;
918 }
919 
921  struct ast_bridge_channel *bridge_channel)
922 {
923  struct ast_channel *c0 = bridge_channel->chan;
924  struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
925  struct ast_stream_topology *req_top;
926  struct ast_stream_topology *existing_top;
927  struct ast_stream_topology *new_top;
928 
929  ast_bridge_channel_stream_map(bridge_channel);
930 
932  == &native_rtp_bridge) {
933  return;
934  }
935 
936  if (c0 == c1) {
937  c1 = AST_LIST_LAST(&bridge->channels)->chan;
938  }
939 
940  if (c0 == c1) {
941  return;
942  }
943 
944  /* If a party renegotiates we want to renegotiate their counterpart to a matching
945  * topology.
946  */
947  ast_channel_lock_both(c0, c1);
948  req_top = ast_channel_get_stream_topology(c0);
949  existing_top = ast_channel_get_stream_topology(c1);
950  new_top = native_rtp_request_stream_topology_update(existing_top, req_top);
951  ast_channel_unlock(c0);
952  ast_channel_unlock(c1);
953 
954  if (!new_top) {
955  /* Failure. We'll just have to live with the current topology. */
956  return;
957  }
958 
959  ast_channel_request_stream_topology_change(c1, new_top, &native_rtp_bridge);
960  ast_stream_topology_free(new_top);
961 }
962 
963 /*!
964  * \internal
965  * \brief Called by the bridge core 'join' callback for each channel joining he bridge
966  */
967 static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
968 {
969  struct ast_stream_topology *req_top;
970  struct ast_stream_topology *existing_top;
971  struct ast_stream_topology *new_top;
972  struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
973  struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
974 
975  ast_debug(2, "Bridge '%s'. Channel '%s' is joining bridge tech\n",
976  bridge->uniqueid, ast_channel_name(bridge_channel->chan));
977 
978  ast_assert(bridge_channel->tech_pvt == NULL);
979 
980  if (bridge_channel->suspended) {
981  /* The channel will rejoin when it is unsuspended */
982  return 0;
983  }
984 
986  if (!bridge_channel->tech_pvt) {
987  return -1;
988  }
989 
990  if (native_rtp_bridge_framehook_attach(bridge_channel)) {
992  bridge_channel->tech_pvt = NULL;
993  return -1;
994  }
995 
996  if (c0 != c1) {
997  /* When both channels are joined we want to try to improve the experience by
998  * raising the number of streams so they match.
999  */
1000  ast_channel_lock_both(c0, c1);
1001  req_top = ast_channel_get_stream_topology(c0);
1002  existing_top = ast_channel_get_stream_topology(c1);
1003  if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
1004  SWAP(req_top, existing_top);
1005  SWAP(c0, c1);
1006  }
1007  new_top = native_rtp_request_stream_topology_update(existing_top, req_top);
1008  ast_channel_unlock(c0);
1009  ast_channel_unlock(c1);
1010 
1011  if (new_top) {
1012  ast_channel_request_stream_topology_change(c1, new_top, &native_rtp_bridge);
1013  ast_stream_topology_free(new_top);
1014  }
1015  }
1016 
1017  native_rtp_bridge_start(bridge, NULL);
1018  return 0;
1019 }
1020 
1021 /*!
1022  * \internal
1023  * \brief Add the channel back into the bridge
1024  */
1025 static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
1026 {
1027  ast_debug(2, "Bridge '%s'. Channel '%s' is unsuspended back to bridge tech\n",
1028  bridge->uniqueid, ast_channel_name(bridge_channel->chan));
1029  native_rtp_bridge_join(bridge, bridge_channel);
1030 }
1031 
1032 /*!
1033  * \internal
1034  * \brief Leave the bridge
1035  */
1036 static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
1037 {
1038  ast_debug(2, "Bridge '%s'. Channel '%s' is leaving bridge tech\n",
1039  bridge->uniqueid, ast_channel_name(bridge_channel->chan));
1040 
1041  if (!bridge_channel->tech_pvt) {
1042  return;
1043  }
1044 
1045  native_rtp_bridge_framehook_detach(bridge_channel);
1046  native_rtp_bridge_stop(bridge, NULL);
1047 
1049  bridge_channel->tech_pvt = NULL;
1050 }
1051 
1052 /*!
1053  * \internal
1054  * \brief Suspend the channel from the bridge
1055  */
1056 static void native_rtp_bridge_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
1057 {
1058  ast_debug(2, "Bridge '%s'. Channel '%s' is suspending from bridge tech\n",
1059  bridge->uniqueid, ast_channel_name(bridge_channel->chan));
1060  native_rtp_bridge_leave(bridge, bridge_channel);
1061 }
1062 
1063 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
1064 {
1065  const struct ast_control_t38_parameters *t38_parameters;
1066  int defer = 0;
1067 
1068  if (!ast_bridge_queue_everyone_else(bridge, bridge_channel, frame)) {
1069  /* This frame was successfully queued so no need to defer */
1070  return 0;
1071  }
1072 
1073  /* Depending on the frame defer it so when the next channel joins it receives it */
1074  switch (frame->frametype) {
1075  case AST_FRAME_CONTROL:
1076  switch (frame->subclass.integer) {
1078  t38_parameters = frame->data.ptr;
1079  switch (t38_parameters->request_response) {
1081  defer = -1;
1082  break;
1083  default:
1084  break;
1085  }
1086  break;
1087  default:
1088  break;
1089  }
1090  break;
1091  default:
1092  break;
1093  }
1094 
1095  return defer;
1096 }
1097 
1098 static int unload_module(void)
1099 {
1100  ast_bridge_technology_unregister(&native_rtp_bridge);
1101  return 0;
1102 }
1103 
1104 static int load_module(void)
1105 {
1106  if (ast_bridge_technology_register(&native_rtp_bridge)) {
1107  unload_module();
1108  return AST_MODULE_LOAD_DECLINE;
1109  }
1110  return AST_MODULE_LOAD_SUCCESS;
1111 }
1112 
1113 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Native RTP bridging module");
static const char type[]
Definition: chan_ooh323.c:109
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
static enum ast_rtp_glue_result rtp_glue_get_current_combined_result(struct ast_channel *c0, struct ast_channel *c1)
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
const ast_string_field uniqueid
Definition: bridge.h:409
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ast_bridge_features * features
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
static struct ast_frame * native_rtp_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static int unload_module(void)
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
ast_framehook_event
These are the types of events that the framehook&#39;s event callback can receive.
Definition: framehook.h:151
void __ao2_cleanup(void *obj)
Definition: astobj2.c:674
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
unsigned int suspended
Set when the stream has been removed/declined.
Definition: stream.h:78
enum ast_control_t38 request_response
int id
Framehook used to intercept certain control frames.
int(* update_peer)(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active)
Definition: rtp_engine.h:756
ast_channel_state
ast_channel states
Definition: channelstate.h:35
Definition: astman.c:222
struct ao2_container * dtmf_hooks
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define ast_str_alloca(init_len)
Definition: strings.h:800
#define SWAP(a, b)
Definition: utils.h:230
struct ast_rtp_glue * cb
glue callbacks
static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
int ast_channel_request_stream_topology_change(struct ast_channel *chan, struct ast_stream_topology *topology, void *change_source)
Request that the stream topology of a channel change.
Definition: channel.c:11167
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
Queue the given frame to everyone else.
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
#define ast_verb(level,...)
Definition: logger.h:463
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1569
static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct ast_bridge_channel *bc0, struct ast_bridge_channel *bc1)
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_frame_subclass subclass
Media Stream API.
static void native_rtp_bridge_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static void rtp_glue_data_destroy(struct rtp_glue_data *glue)
Internal structure which contains instance information about bridged RTP channels.
int done
Definition: test_amihooks.c:48
struct rtp_glue_stream video
int(* allow_vrtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance)
Used to prevent two channels from remotely bridging video rtp if the channel tech has a reason for pr...
Definition: rtp_engine.h:747
static struct ast_bridge_technology native_rtp_bridge
#define ao2_bump(obj)
Definition: astobj2.h:491
static int rtp_glue_data_get(struct ast_channel *c0, struct rtp_glue_data *glue0, struct ast_channel *c1, struct rtp_glue_data *glue1)
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
static void rtp_glue_data_init(struct rtp_glue_data *glue)
static struct ast_stream_topology * native_rtp_request_stream_topology_update(struct ast_stream_topology *existing_topology, struct ast_stream_topology *requested_topology)
void ast_rtp_instance_set_bridged(struct ast_rtp_instance *instance, struct ast_rtp_instance *bridged)
Set the other RTP instance that an instance is bridged to.
Definition: rtp_engine.c:2244
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
Internal structure which contains bridged RTP channel hook data.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10735
static int native_rtp_framehook_consume(void *data, enum ast_frame_type type)
General Asterisk PBX channel definitions.
int(* dtmf_compatible)(struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
Definition: rtp_engine.h:671
enum ast_rtp_glue_result(* get_rtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying audio.
Definition: rtp_engine.h:729
struct ast_rtp_instance * instance
RTP instance.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static void rtp_glue_data_reset(struct rtp_glue_data *glue)
static void native_rtp_bridge_channel_data_free(struct native_rtp_bridge_channel_data *data)
Channel Bridging API.
Asterisk internal frame definitions.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_rtp_glue * remote_cb
Glue callbacks to bring remote channel streams back to Asterisk.
static int native_rtp_bridge_capable(struct ast_channel *chan)
struct ast_rtp_engine * ast_rtp_instance_get_engine(struct ast_rtp_instance *instance)
Get the RTP engine in use on an RTP instance.
Definition: rtp_engine.c:2700
static int native_rtp_bridge_compatible(struct ast_bridge *bridge)
enum ast_rtp_glue_result result
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
ast_rtp_glue_result
Definition: rtp_engine.h:158
void(* get_codec)(struct ast_channel *chan, struct ast_format_cap *result_cap)
Callback for retrieving codecs that the channel can do. Result returned in result_cap.
Definition: rtp_engine.h:761
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
#define ast_bridge_technology_register(technology)
See __ast_bridge_technology_register()
ast_frame_type
Frame types.
Structure that contains information about a bridge.
Definition: bridge.h:357
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
Definition: bridge.c:265
void * ast_channel_get_stream_topology_change_source(struct ast_channel *chan)
Retrieve the source that initiated the last stream topology change.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct native_rtp_framehook_data * hook_data
Channel&#39;s hook data.
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
unsigned int ast_format_cap_get_format_framing(const struct ast_format_cap *cap, const struct ast_format *format)
Get the framing for a format.
Definition: format_cap.c:443
#define AST_LIST_LAST(head)
Returns the last entry contained in a list.
Definition: linkedlists.h:428
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
static int load_module(void)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
Set when the stream is sending media only.
Definition: stream.h:86
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel)
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
int(* allow_rtp_remote)(struct ast_channel *chan1, struct ast_rtp_instance *instance)
Used to prevent two channels from remotely bridging audio rtp if the channel tech has a reason for pr...
Definition: rtp_engine.h:735
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
void * tech_pvt
Private information unique to the bridge technology.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:480
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
struct ast_bridge_channels_list channels
Definition: bridge.h:371
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
int ast_channel_has_hook_requiring_audio(struct ast_channel *chan)
Check if the channel has any active hooks that require audio.
Definition: channel.c:2530
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
Structure that is the essence of a bridge technology.
struct rtp_glue_stream audio
static PGresult * result
Definition: cel_pgsql.c:88
int(* local_bridge)(struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
Definition: rtp_engine.h:663
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Definition: rtp_engine.c:2137
static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel)
Maps a channel&#39;s stream topology to and from the bridge.
Data structure associated with a single frame of data.
static struct native_rtp_bridge_channel_data * native_rtp_bridge_channel_data_alloc(void)
enum ast_rtp_glue_result result
glue result
static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Forward declarations.
union ast_frame::@263 data
enum ast_frame_type frametype
enum ast_rtp_glue_result(* get_vrtp_info)(struct ast_channel *chan, struct ast_rtp_instance **instance)
Callback for retrieving the RTP instance carrying video.
Definition: rtp_engine.h:741
unsigned int detached
Set when this framehook has been detached.
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
static void native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channel *target)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_rtp_glue * ast_rtp_instance_get_glue(const char *type)
Get the RTP glue that binds a channel to the RTP engine.
Definition: rtp_engine.c:2206
Pluggable RTP Architecture.
Bridging API.
Asterisk module definitions.
struct ast_format * ast_channel_rawwriteformat(struct ast_channel *chan)
struct rtp_glue_data glue
Channel&#39;s cached RTP glue information.
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
unsigned int num_channels
Definition: bridge.h:381
Set when the stream is receiving media only.
Definition: stream.h:90
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel)
static void native_rtp_stream_topology_changed(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if any joint capabilities exist between two capabilities structures.
Definition: format_cap.c:655