Asterisk - The Open Source Telephony Project  18.5.0
core_unreal.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  * Richard Mudgett <[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 /*!
20  * \file
21  * \brief Unreal channel derivatives framework for channel drivers like local channels.
22  *
23  * \author Richard Mudgett <[email protected]>
24  *
25  * See Also:
26  * \arg \ref AstCREDITS
27  */
28 
29 /*** MODULEINFO
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 #include "asterisk/causes.h"
36 #include "asterisk/channel.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/musiconhold.h"
40 #include "asterisk/astobj2.h"
41 #include "asterisk/bridge.h"
42 #include "asterisk/core_unreal.h"
43 #include "asterisk/stream.h"
44 
45 static unsigned int name_sequence = 0;
46 
47 void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
48 {
49  struct ast_channel *chan = NULL;
50  struct ast_channel *owner = NULL;
51 
52  ao2_lock(p);
53  for (;;) {
54  if (p->chan) {
55  chan = p->chan;
56  ast_channel_ref(chan);
57  }
58  if (p->owner) {
59  owner = p->owner;
60  ast_channel_ref(owner);
61  }
62  ao2_unlock(p);
63 
64  /* if we don't have both channels, then this is very easy */
65  if (!owner || !chan) {
66  if (owner) {
67  ast_channel_lock(owner);
68  } else if(chan) {
69  ast_channel_lock(chan);
70  }
71  } else {
72  /* lock both channels first, then get the pvt lock */
73  ast_channel_lock_both(chan, owner);
74  }
75  ao2_lock(p);
76 
77  /* Now that we have all the locks, validate that nothing changed */
78  if (p->owner != owner || p->chan != chan) {
79  if (owner) {
80  ast_channel_unlock(owner);
81  owner = ast_channel_unref(owner);
82  }
83  if (chan) {
84  ast_channel_unlock(chan);
85  chan = ast_channel_unref(chan);
86  }
87  continue;
88  }
89 
90  break;
91  }
92  *outowner = p->owner;
93  *outchan = p->chan;
94 }
95 
96 /* Called with ast locked */
97 int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int datalen)
98 {
99  int res = 0;
100  struct ast_unreal_pvt *p;
101  struct ast_channel *otherchan = NULL;
102  ast_chan_write_info_t *write_info;
103  char *info_data;
104 
105  if (option != AST_OPTION_CHANNEL_WRITE) {
106  return -1;
107  }
108 
109  write_info = data;
110 
111  if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
112  ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
113  return -1;
114  }
115 
116  info_data = write_info->data;
117  if (!strcmp(write_info->function, "CHANNEL")) {
118  if (!strncasecmp(info_data, "hangup_handler_", 15)) {
119  /* Block CHANNEL(hangup_handler_xxx) writes to the other unreal channel. */
120  return 0;
121  }
122 
123  /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
124  if (!strcasecmp(info_data, "accountcode")) {
125  info_data = "peeraccount";
126  } else if (!strcasecmp(info_data, "peeraccount")) {
127  info_data = "accountcode";
128  }
129  }
130 
131  /* get the tech pvt */
132  if (!(p = ast_channel_tech_pvt(ast))) {
133  return -1;
134  }
135  ao2_ref(p, 1);
136  ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
137 
138  /* get the channel we are supposed to write to */
139  ao2_lock(p);
140  otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
141  if (!otherchan || otherchan == write_info->chan) {
142  res = -1;
143  otherchan = NULL;
144  ao2_unlock(p);
145  goto setoption_cleanup;
146  }
147  ast_channel_ref(otherchan);
148 
149  /* clear the pvt lock before grabbing the channel */
150  ao2_unlock(p);
151 
152  ast_channel_lock(otherchan);
153  res = write_info->write_fn(otherchan, write_info->function, info_data, write_info->value);
154  ast_channel_unlock(otherchan);
155 
156 setoption_cleanup:
157  ao2_ref(p, -1);
158  if (otherchan) {
159  ast_channel_unref(otherchan);
160  }
161  ast_channel_lock(ast); /* Lock back before we leave */
162  return res;
163 }
164 
165 /* Called with ast locked */
166 int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
167 {
168  struct ast_unreal_pvt *p;
169  struct ast_channel *peer;
170  struct ast_channel *other;
171  int res = 0;
172 
173  if (option != AST_OPTION_T38_STATE) {
174  /* AST_OPTION_T38_STATE is the only supported option at this time */
175  return -1;
176  }
177 
178  /* for some reason the channel is not locked in channel.c when this function is called */
179  if (!(p = ast_channel_tech_pvt(ast))) {
180  return -1;
181  }
182 
183  ao2_lock(p);
184  other = AST_UNREAL_IS_OUTBOUND(ast, p) ? p->owner : p->chan;
185  if (!other) {
186  ao2_unlock(p);
187  return -1;
188  }
189  ast_channel_ref(other);
190  ao2_unlock(p);
191  ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
192 
193  peer = ast_channel_bridge_peer(other);
194  if (peer) {
195  res = ast_channel_queryoption(peer, option, data, datalen, 0);
196  ast_channel_unref(peer);
197  }
198  ast_channel_unref(other);
199  ast_channel_lock(ast); /* Lock back before we leave */
200 
201  return res;
202 }
203 
204 /*!
205  * \brief queue a frame onto either the p->owner or p->chan
206  *
207  * \note the ast_unreal_pvt MUST have it's ref count bumped before entering this function and
208  * decremented after this function is called. This is a side effect of the deadlock
209  * avoidance that is necessary to lock 2 channels and a tech_pvt. Without a ref counted
210  * ast_unreal_pvt, it is impossible to guarantee it will not be destroyed by another thread
211  * during deadlock avoidance.
212  */
213 static int unreal_queue_frame(struct ast_unreal_pvt *p, int isoutbound, struct ast_frame *f,
214  struct ast_channel *us, int us_locked)
215 {
216  struct ast_channel *other;
217 
218  /* Recalculate outbound channel */
219  other = isoutbound ? p->owner : p->chan;
220  if (!other) {
221  return 0;
222  }
223 
224  /* do not queue media frames if a generator is on both unreal channels */
225  if (us
227  && ast_channel_generator(us)
228  && ast_channel_generator(other)) {
229  return 0;
230  }
231 
232  /* grab a ref on the channel before unlocking the pvt,
233  * other can not go away from us now regardless of locking */
234  ast_channel_ref(other);
235  if (us && us_locked) {
236  ast_channel_unlock(us);
237  }
238  ao2_unlock(p);
239 
242  }
243  ast_queue_frame(other, f);
244 
245  other = ast_channel_unref(other);
246  if (us && us_locked) {
247  ast_channel_lock(us);
248  }
249  ao2_lock(p);
250 
251  return 0;
252 }
253 
255 {
256  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
257  int isoutbound;
258  int res = -1;
259 
260  if (!p) {
261  return -1;
262  }
263 
264  ao2_ref(p, 1);
265  ao2_lock(p);
266  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
267  if (isoutbound) {
268  /* Pass along answer since somebody answered us */
269  struct ast_frame answer = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
270 
271  res = unreal_queue_frame(p, isoutbound, &answer, ast, 1);
272  } else {
273  ast_log(LOG_WARNING, "Huh? %s is being asked to answer?\n",
274  ast_channel_name(ast));
275  }
276  ao2_unlock(p);
277  ao2_ref(p, -1);
278  return res;
279 }
280 
281 /*!
282  * \internal
283  * \brief Check and optimize out the unreal channels between bridges.
284  * \since 12.0.0
285  *
286  * \param ast Channel writing a frame into the unreal channels.
287  * \param p Unreal channel private.
288  *
289  * \note It is assumed that ast is locked.
290  * \note It is assumed that p is locked.
291  *
292  * \retval 0 if unreal channels were not optimized out.
293  * \retval non-zero if unreal channels were optimized out.
294  */
295 static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
296 {
297  int res = 0;
298 
299  /* Do a few conditional checks early on just to see if this optimization is possible */
300  if (ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION) || !p->chan || !p->owner) {
301  return res;
302  }
303 
304  if (ast == p->owner) {
305  res = ast_bridge_unreal_optimize_out(p->owner, p->chan, p);
306  } else if (ast == p->chan) {
307  res = ast_bridge_unreal_optimize_out(p->chan, p->owner, p);
308  }
309 
310  return res;
311 }
312 
314 {
315  return &ast_null_frame;
316 }
317 
318 int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
319 {
320  return ast_unreal_write_stream(ast, -1, f);
321 }
322 
323 int ast_unreal_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)
324 {
325  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
326  int res = -1;
327 
328  if (!p) {
329  return -1;
330  }
331 
332  /* If we are told to write a frame with a type that has no corresponding
333  * stream on the channel then drop it.
334  */
335  if (f->frametype == AST_FRAME_VOICE) {
337  return 0;
338  }
339  } else if (f->frametype == AST_FRAME_VIDEO ||
342  return 0;
343  }
344  }
345 
346  /* Update the frame to reflect the stream */
347  f->stream_num = stream_num;
348 
349  /* Just queue for delivery to the other side */
350  ao2_ref(p, 1);
351  ao2_lock(p);
352  switch (f->frametype) {
353  case AST_FRAME_VOICE:
354  case AST_FRAME_VIDEO:
355  if (got_optimized_out(ast, p)) {
356  break;
357  }
358  /* fall through */
359  default:
360  res = unreal_queue_frame(p, AST_UNREAL_IS_OUTBOUND(ast, p), f, ast, 1);
361  break;
362  }
363  ao2_unlock(p);
364  ao2_ref(p, -1);
365 
366  return res;
367 }
368 
369 int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
370 {
371  struct ast_unreal_pvt *p = ast_channel_tech_pvt(newchan);
372  struct ast_bridge *bridge_owner;
373  struct ast_bridge *bridge_chan;
374 
375  if (!p) {
376  return -1;
377  }
378 
379  ao2_lock(p);
380 
381  if ((p->owner != oldchan) && (p->chan != oldchan)) {
382  ast_log(LOG_WARNING, "Old channel %p wasn't %p or %p\n", oldchan, p->owner, p->chan);
383  ao2_unlock(p);
384  return -1;
385  }
386  if (p->owner == oldchan) {
387  p->owner = newchan;
388  } else {
389  p->chan = newchan;
390  }
391 
392  if (ast_check_hangup(newchan) || !p->owner || !p->chan) {
393  ao2_unlock(p);
394  return 0;
395  }
396 
397  /* Do not let a masquerade cause an unreal channel to be bridged to itself! */
398  bridge_owner = ast_channel_internal_bridge(p->owner);
399  bridge_chan = ast_channel_internal_bridge(p->chan);
400  if (bridge_owner && bridge_owner == bridge_chan) {
401  ast_log(LOG_WARNING, "You can not bridge an unreal channel (%s) to itself!\n",
402  ast_channel_name(newchan));
403  ao2_unlock(p);
404  ast_queue_hangup(newchan);
405  return -1;
406  }
407 
408  ao2_unlock(p);
409  return 0;
410 }
411 
412 /*!
413  * \internal
414  * \brief Queue up a frame representing the indication as a control frame.
415  * \since 12.0.0
416  *
417  * \param p Unreal private structure.
418  * \param ast Channel indicating the condition.
419  * \param condition What is being indicated.
420  * \param data Extra data.
421  * \param datalen Length of extra data.
422  *
423  * \retval 0 on success.
424  * \retval AST_T38_REQUEST_PARMS if successful and condition is AST_CONTROL_T38_PARAMETERS.
425  * \retval -1 on error.
426  */
427 static int unreal_queue_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition, const void *data, size_t datalen)
428 {
429  int res = 0;
430  int isoutbound;
431 
432  ao2_lock(p);
433  /*
434  * Block -1 stop tones events if we are to be optimized out. We
435  * don't need a flurry of these events on an unreal channel chain
436  * when initially connected to slow the optimization process.
437  */
438  if (0 <= condition || ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION)) {
439  struct ast_frame f = {
441  .subclass.integer = condition,
442  .data.ptr = (void *) data,
443  .datalen = datalen,
444  };
445 
446  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
447  res = unreal_queue_frame(p, isoutbound, &f, ast, 1);
448  if (!res
449  && condition == AST_CONTROL_T38_PARAMETERS
450  && datalen == sizeof(struct ast_control_t38_parameters)) {
451  const struct ast_control_t38_parameters *parameters = data;
452 
453  if (parameters->request_response == AST_T38_REQUEST_PARMS) {
454  res = AST_T38_REQUEST_PARMS;
455  }
456  }
457  } else {
458  ast_debug(4, "Blocked indication %d\n", condition);
459  }
460  ao2_unlock(p);
461 
462  return res;
463 }
464 
465 /*!
466  * \internal
467  * \brief Handle COLP and redirecting conditions.
468  * \since 12.0.0
469  *
470  * \param p Unreal private structure.
471  * \param ast Channel indicating the condition.
472  * \param condition What is being indicated.
473  *
474  * \retval 0 on success.
475  * \retval -1 on error.
476  */
477 static int unreal_colp_redirect_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
478 {
479  struct ast_channel *my_chan;
480  struct ast_channel *my_owner;
481  struct ast_channel *this_channel;
482  struct ast_channel *the_other_channel;
483  int isoutbound;
484  int res = 0;
485  unsigned char frame_data[1024];
486  struct ast_frame f = {
488  .subclass.integer = condition,
489  .data.ptr = frame_data,
490  };
491 
492  /*
493  * A connected line update frame may only contain a partial
494  * amount of data, such as just a source, or just a ton, and not
495  * the full amount of information. However, the collected
496  * information is all stored in the outgoing channel's
497  * connectedline structure, so when receiving a connected line
498  * update on an outgoing unreal channel, we need to transmit the
499  * collected connected line information instead of whatever
500  * happens to be in this control frame. The same applies for
501  * redirecting information, which is why it is handled here as
502  * well.
503  */
504  ast_channel_unlock(ast);
505  ast_unreal_lock_all(p, &my_chan, &my_owner);
506  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
507  if (isoutbound) {
508  this_channel = p->chan;
509  the_other_channel = p->owner;
510  } else {
511  this_channel = p->owner;
512  the_other_channel = p->chan;
513  }
514  if (the_other_channel) {
515  if (condition == AST_CONTROL_CONNECTED_LINE) {
517  ast_channel_connected(this_channel));
518  f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data),
519  ast_channel_connected(this_channel), NULL);
520  } else {
521  f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data),
522  ast_channel_redirecting(this_channel), NULL);
523  }
524  }
525  if (my_chan) {
526  ast_channel_unlock(my_chan);
527  ast_channel_unref(my_chan);
528  }
529  if (my_owner) {
530  ast_channel_unlock(my_owner);
531  ast_channel_unref(my_owner);
532  }
533  if (the_other_channel) {
534  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
535  }
536  ao2_unlock(p);
537  ast_channel_lock(ast);
538 
539  return res;
540 }
541 
542 /*!
543  * \internal
544  * \brief Handle stream topology change request.
545  * \since 16.12.0
546  * \since 17.6.0
547  *
548  * \param p Unreal private structure.
549  * \param ast Channel indicating the condition.
550  * \param topology The requested topology.
551  *
552  * \retval 0 on success.
553  * \retval -1 on error.
554  */
555 static int unreal_colp_stream_topology_request_change(struct ast_unreal_pvt *p, struct ast_channel *ast, const struct ast_stream_topology *topology)
556 {
557  struct ast_stream_topology *this_channel_topology;
558  struct ast_stream_topology *the_other_channel_topology;
559  int i;
560  struct ast_stream *stream;
561  struct ast_channel *my_chan;
562  struct ast_channel *my_owner;
563  struct ast_channel *this_channel;
564  struct ast_channel *the_other_channel;
565  int res = 0;
566 
567  this_channel_topology = ast_stream_topology_clone(topology);
568  if (!this_channel_topology) {
569  return -1;
570  }
571 
572  the_other_channel_topology = ast_stream_topology_clone(topology);
573  if (!the_other_channel_topology) {
574  ast_stream_topology_free(this_channel_topology);
575  return -1;
576  }
577 
578  /* We swap the stream state on the other channel because it is as if the channel is
579  * connected to an external endpoint, so the perspective changes.
580  */
581  for (i = 0; i < ast_stream_topology_get_count(the_other_channel_topology); ++i) {
582  stream = ast_stream_topology_get_stream(the_other_channel_topology, i);
583 
586  } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
588  }
589  }
590 
591  ast_channel_unlock(ast);
592  ast_unreal_lock_all(p, &my_chan, &my_owner);
593  if (AST_UNREAL_IS_OUTBOUND(ast, p)) {
594  this_channel = p->chan;
595  the_other_channel = p->owner;
596  } else {
597  this_channel = p->owner;
598  the_other_channel = p->chan;
599  }
600  if (this_channel) {
601  ast_channel_set_stream_topology(this_channel, this_channel_topology);
603  }
604  if (the_other_channel) {
605  ast_channel_set_stream_topology(the_other_channel, the_other_channel_topology);
607  }
608  if (my_chan) {
609  ast_channel_unlock(my_chan);
610  ast_channel_unref(my_chan);
611  }
612  if (my_owner) {
613  ast_channel_unlock(my_owner);
614  ast_channel_unref(my_owner);
615  }
616  ao2_unlock(p);
617  ast_channel_lock(ast);
618 
619  return res;
620 }
621 
622 int ast_unreal_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
623 {
624  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
625  int res = 0;
626  struct ast_channel *chan = NULL;
627  struct ast_channel *owner = NULL;
628  const struct ast_control_t38_parameters *parameters;
629 
630  if (!p) {
631  return -1;
632  }
633 
634  ao2_ref(p, 1); /* ref for unreal_queue_frame */
635 
636  switch (condition) {
638  /*
639  * Always block this because this is the channel being
640  * masqueraded; not anything down the chain.
641  */
642  break;
645  res = unreal_colp_redirect_indicate(p, ast, condition);
646  break;
647  case AST_CONTROL_HOLD:
649  ast_moh_start(ast, data, NULL);
650  break;
651  }
652  res = unreal_queue_indicate(p, ast, condition, data, datalen);
653  break;
654  case AST_CONTROL_UNHOLD:
656  ast_moh_stop(ast);
657  break;
658  }
659  res = unreal_queue_indicate(p, ast, condition, data, datalen);
660  break;
661  case AST_CONTROL_RINGING:
662  /* Don't queue ringing frames if the channel is not in a "ring" state. Otherwise,
663  * the real channel on the other end will likely start a playtones generator. It is
664  * possible that this playtones generator will never be stopped under certain
665  * circumstances.
666  */
667  if (ast_channel_state(ast) == AST_STATE_RING) {
668  res = unreal_queue_indicate(p, ast, condition, data, datalen);
669  } else {
670  res = -1;
671  }
672  break;
674  /* Return -1 so that asterisk core will correctly set up hangupcauses. */
675  unreal_queue_indicate(p, ast, condition, data, datalen);
676  res = -1;
677  break;
679  if (ast_channel_is_multistream(ast)) {
680  res = unreal_colp_stream_topology_request_change(p, ast, data);
681  }
682  break;
684  parameters = data;
685  if (parameters->request_response == AST_T38_NEGOTIATED) {
686  struct ast_stream *stream;
687  struct ast_stream_topology *new_topology;
688 
689  stream = ast_stream_alloc("local_fax", AST_MEDIA_TYPE_IMAGE);
690  if (!stream) {
691  ast_log(LOG_ERROR, "Failed to allocate memory for stream.\n");
692  res = -1;
693  break;
694  }
695  new_topology = ast_stream_topology_alloc();
696  if (!new_topology) {
697  ast_log(LOG_ERROR, "Failed to allocate memory for stream topology.\n");
698  ast_free(stream);
699  res = -1;
700  break;
701  }
702  ast_stream_topology_append_stream(new_topology, stream);
703 
704  /*
705  * Lock both parts of the local channel so we can store their topologies and replace them with
706  * one that has a stream with type IMAGE. We can just hold the reference on the unreal_pvt
707  * structure and bump it, then steal the ref later when we are restoring the topology.
708  *
709  * We use ast_unreal_lock_all here because we don't know if the ;1 or ;2 side will get the
710  * signaling and we need to be sure that the locking order is the same to prevent possible
711  * deadlocks.
712  */
713  ast_channel_unlock(ast);
714  ast_unreal_lock_all(p, &chan, &owner);
715 
716  if (owner) {
718  ast_channel_set_stream_topology(owner, new_topology);
719  }
720 
721  if (chan) {
723 
724  /* Bump the ref for new_topology, since it will be used by both sides of the local channel */
725  ao2_ref(new_topology, +1);
726  ast_channel_set_stream_topology(chan, new_topology);
727  }
728 
729  ao2_unlock(p);
730  ast_channel_lock(ast);
731  } else if (parameters->request_response == AST_T38_TERMINATED) {
732  /*
733  * Lock both parts of the local channel so we can restore their topologies to the original.
734  * The topology should be on the unreal_pvt structure, with a ref that we can steal. Same
735  * conditions as above.
736  */
737  ast_channel_unlock(ast);
738  ast_unreal_lock_all(p, &chan, &owner);
739 
740  if (owner) {
743  }
744 
745  if (chan) {
747  p->chan_old_topology = NULL;
748  }
749 
750  ao2_unlock(p);
751  ast_channel_lock(ast);
752  }
753 
754  /*
755  * We unlock ast_unreal_pvt in the above conditionals since there's no way to
756  * tell if it's been unlocked already or not when we get to this point, but
757  * if either of these are not NULL, we know that they are locked and need to
758  * unlock them.
759  */
760  if (owner) {
761  ast_channel_unlock(owner);
762  ast_channel_unref(owner);
763  }
764 
765  if (chan) {
766  ast_channel_unlock(chan);
767  ast_channel_unref(chan);
768  }
769  /* Fall through for all T38 conditions */
770  default:
771  res = unreal_queue_indicate(p, ast, condition, data, datalen);
772  break;
773  }
774 
775  ao2_ref(p, -1);
776  return res;
777 }
778 
780 {
781  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
782  int res = -1;
783  struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
784  int isoutbound;
785 
786  if (!p) {
787  return -1;
788  }
789 
790  ao2_ref(p, 1); /* ref for unreal_queue_frame */
791  ao2_lock(p);
792  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
793  f.subclass.integer = digit;
794  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
795  ao2_unlock(p);
796  ao2_ref(p, -1);
797 
798  return res;
799 }
800 
801 int ast_unreal_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
802 {
803  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
804  int res = -1;
805  struct ast_frame f = { AST_FRAME_DTMF_END, };
806  int isoutbound;
807 
808  if (!p) {
809  return -1;
810  }
811 
812  ao2_ref(p, 1); /* ref for unreal_queue_frame */
813  ao2_lock(p);
814  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
815  f.subclass.integer = digit;
816  f.len = duration;
817  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
818  ao2_unlock(p);
819  ao2_ref(p, -1);
820 
821  return res;
822 }
823 
824 int ast_unreal_sendtext(struct ast_channel *ast, const char *text)
825 {
826  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
827  int res = -1;
828  struct ast_frame f = { AST_FRAME_TEXT, };
829  int isoutbound;
830 
831  if (!p) {
832  return -1;
833  }
834 
835  ao2_ref(p, 1); /* ref for unreal_queue_frame */
836  ao2_lock(p);
837  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
838  f.data.ptr = (char *) text;
839  f.datalen = strlen(text) + 1;
840  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
841  ao2_unlock(p);
842  ao2_ref(p, -1);
843  return res;
844 }
845 
846 int ast_unreal_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
847 {
848  struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
849  int res = -1;
850  struct ast_frame f = { AST_FRAME_HTML, };
851  int isoutbound;
852 
853  if (!p) {
854  return -1;
855  }
856 
857  ao2_ref(p, 1); /* ref for unreal_queue_frame */
858  ao2_lock(p);
859  isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
861  f.data.ptr = (char *)data;
862  f.datalen = datalen;
863  res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
864  ao2_unlock(p);
865  ao2_ref(p, -1);
866 
867  return res;
868 }
869 
870 void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
871 {
872  struct ast_var_t *varptr;
873  struct ast_var_t *clone_var;
874 
876 
877  /*
878  * Note that cid_num and cid_name aren't passed in the
879  * ast_channel_alloc calls in ast_unreal_new_channels(). It's
880  * done here instead.
881  */
883 
885 
886  /* Crossover the CallerID and conected-line to cross the unreal bridge. */
889 
890  ast_channel_language_set(semi2, ast_channel_language(semi1));
891  ast_channel_musicclass_set(semi2, ast_channel_musicclass(semi1));
892  ast_channel_parkinglot_set(semi2, ast_channel_parkinglot(semi1));
893 
894  /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
895  ast_channel_accountcode_set(semi2, ast_channel_peeraccount(semi1));
896  ast_channel_peeraccount_set(semi2, ast_channel_accountcode(semi1));
897 
899 
900  /*
901  * Make sure we inherit the AST_CAUSE_ANSWERED_ELSEWHERE if it's
902  * set on the queue/dial call request in the dialplan.
903  */
906  }
907 
908  /*
909  * Copy the channel variables from the semi1 channel to the
910  * outgoing channel.
911  *
912  * Note that due to certain assumptions, they MUST be in the
913  * same order.
914  */
916  clone_var = ast_var_assign(varptr->name, varptr->value);
917  if (clone_var) {
920  ast_var_value(clone_var));
921  }
922  }
923  ast_channel_datastore_inherit(semi1, semi2);
924 
926 }
927 
928 int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
929 {
930  struct ast_bridge_features *features;
931  struct ast_channel *chan;
932  struct ast_channel *owner;
933  ast_callid bridge_callid;
934  RAII_VAR(struct ast_unreal_pvt *, p, NULL, ao2_cleanup);
935 
936  ast_bridge_lock(bridge);
937  bridge_callid = bridge->callid;
938  ast_bridge_unlock(bridge);
939 
940  {
941  SCOPED_CHANNELLOCK(lock, ast);
942  p = ast_channel_tech_pvt(ast);
943  if (!p) {
944  return -1;
945  }
946  ao2_ref(p, +1);
947  }
948 
949  {
950  SCOPED_AO2LOCK(lock, p);
951  chan = p->chan;
952  if (!chan) {
953  return -1;
954  }
955 
956  owner = p->owner;
957  if (!owner) {
958  return -1;
959  }
960 
961  ast_channel_ref(chan);
962  ast_channel_ref(owner);
963  }
964 
965  if (bridge_callid) {
966  ast_callid chan_callid;
967  ast_callid owner_callid;
968 
969  /* chan side call ID setting */
970  ast_channel_lock(chan);
971 
972  chan_callid = ast_channel_callid(chan);
973  if (!chan_callid) {
974  ast_channel_callid_set(chan, bridge_callid);
975  }
976  ast_channel_unlock(chan);
977 
978  /* owner side call ID setting */
979  ast_channel_lock(owner);
980 
981  owner_callid = ast_channel_callid(owner);
982  if (!owner_callid) {
983  ast_channel_callid_set(owner, bridge_callid);
984  }
985 
986  ast_channel_unlock(owner);
987  }
988 
989  /* We are done with the owner now that its call ID matches the bridge */
990  ast_channel_unref(owner);
991  owner = NULL;
992 
993  features = ast_bridge_features_new();
994  if (!features) {
995  ast_channel_unref(chan);
996  return -1;
997  }
998 
999  ast_set_flag(&features->feature_flags, flags);
1000 
1001  /* Impart the semi2 channel into the bridge */
1002  if (ast_bridge_impart(bridge, chan, NULL, features,
1004  ast_channel_unref(chan);
1005  return -1;
1006  }
1007 
1008  /* The bridge thread now controls the chan ref from the ast_unreal_pvt */
1009  ao2_lock(p);
1011  ao2_unlock(p);
1012 
1013  ast_channel_unref(chan);
1014 
1015  return 0;
1016 }
1017 
1018 int ast_unreal_hangup(struct ast_unreal_pvt *p, struct ast_channel *ast)
1019 {
1020  int hangup_chan = 0;
1021  int res = 0;
1022  int cause;
1023  struct ast_channel *owner = NULL;
1024  struct ast_channel *chan = NULL;
1025 
1026  /* the pvt isn't going anywhere, it has a ref */
1027  ast_channel_unlock(ast);
1028 
1029  /* lock everything */
1030  ast_unreal_lock_all(p, &chan, &owner);
1031 
1032  if (ast != chan && ast != owner) {
1033  res = -1;
1034  goto unreal_hangup_cleanup;
1035  }
1036 
1037  cause = ast_channel_hangupcause(ast);
1038 
1039  ast_log(LOG_WARNING, "Unreal hangup\n");
1040 
1041  if (ast == p->chan) {
1042  /* Outgoing side is hanging up. */
1044  p->chan = NULL;
1045  if (p->owner) {
1046  const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
1047 
1048  if (status) {
1050  pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
1051  }
1053  }
1054  } else {
1055  /* Owner side is hanging up. */
1056  p->owner = NULL;
1057  if (p->chan) {
1058  if (cause == AST_CAUSE_ANSWERED_ELSEWHERE) {
1060  ast_debug(2, "%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
1061  ast_channel_name(p->chan));
1062  }
1064  /*
1065  * Need to actually hangup p->chan since nothing else is taking
1066  * care of it.
1067  */
1068  hangup_chan = 1;
1069  } else {
1070  ast_queue_hangup_with_cause(p->chan, cause);
1071  }
1072  }
1073  }
1074 
1075  /* this is one of our locked channels, doesn't matter which */
1077  ao2_ref(p, -1);
1078 
1079 unreal_hangup_cleanup:
1080  ao2_unlock(p);
1081  if (owner) {
1082  ast_channel_unlock(owner);
1083  ast_channel_unref(owner);
1084  }
1085  if (chan) {
1086  ast_channel_unlock(chan);
1087  if (hangup_chan) {
1088  ast_hangup(chan);
1089  }
1090  ast_channel_unref(chan);
1091  }
1092 
1093  /* leave with the channel locked that came in */
1094  ast_channel_lock(ast);
1095 
1096  return res;
1097 }
1098 
1099 void ast_unreal_destructor(void *vdoomed)
1100 {
1101  struct ast_unreal_pvt *doomed = vdoomed;
1102 
1103  ao2_cleanup(doomed->reqcap);
1104  doomed->reqcap = NULL;
1106  doomed->reqtopology = NULL;
1108  ao2_cleanup(doomed->chan_old_topology);
1109 }
1110 
1111 struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
1112 {
1113  struct ast_stream_topology *topology;
1114  struct ast_unreal_pvt *unreal;
1115 
1117  if (!topology) {
1118  return NULL;
1119  }
1120 
1121  unreal = ast_unreal_alloc_stream_topology(size, destructor, topology);
1122 
1123  ast_stream_topology_free(topology);
1124 
1125  return unreal;
1126 }
1127 
1129 {
1130  struct ast_unreal_pvt *unreal;
1131 
1132  static const struct ast_jb_conf jb_conf = {
1133  .flags = 0,
1134  .max_size = -1,
1135  .resync_threshold = -1,
1136  .impl = "",
1137  .target_extra = -1,
1138  };
1139 
1140  unreal = ao2_alloc(size, destructor);
1141  if (!unreal) {
1142  return NULL;
1143  }
1144 
1145  unreal->reqtopology = ast_stream_topology_clone(topology);
1146  if (!unreal->reqtopology) {
1147  ao2_ref(unreal, -1);
1148  return NULL;
1149  }
1150 
1151  unreal->reqcap = ast_stream_topology_get_formats(topology);
1152  if (!unreal->reqcap) {
1153  ao2_ref(unreal, -1);
1154  return NULL;
1155  }
1156 
1157  memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
1158 
1159  return unreal;
1160 }
1161 
1163  const struct ast_channel_tech *tech, int semi1_state, int semi2_state,
1164  const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
1165  const struct ast_channel *requestor, ast_callid callid)
1166 {
1167  struct ast_channel *owner;
1168  struct ast_channel *chan;
1169  RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
1170  struct ast_assigned_ids id1 = {NULL, NULL};
1171  struct ast_assigned_ids id2 = {NULL, NULL};
1172  int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
1173  struct ast_stream_topology *topology;
1174 
1175  /* set unique ids for the two channels */
1176  if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
1177  id1.uniqueid = assignedids->uniqueid;
1178  id2.uniqueid = assignedids->uniqueid2;
1179  }
1180 
1181  /* if id1 given but not id2, use default of id1;2 */
1182  if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
1183  char *uniqueid2;
1184 
1185  uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 3);
1186  strcpy(uniqueid2, id1.uniqueid);/* Safe */
1187  strcat(uniqueid2, ";2");/* Safe */
1188  id2.uniqueid = uniqueid2;
1189  }
1190 
1191  /* We need to create a topology to place on the first channel, as we can't
1192  * share a single one between both.
1193  */
1194  topology = ast_stream_topology_clone(p->reqtopology);
1195  if (!topology) {
1196  return NULL;
1197  }
1198 
1199  /*
1200  * Allocate two new Asterisk channels
1201  *
1202  * Make sure that the ;2 channel gets the same linkedid as ;1.
1203  * You can't pass linkedid to both allocations since if linkedid
1204  * isn't set, then each channel will generate its own linkedid.
1205  */
1206  owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
1207  exten, context, &id1, requestor, 0,
1208  "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
1209  if (!owner) {
1210  ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
1211  ast_stream_topology_free(topology);
1212  return NULL;
1213  }
1214 
1215  if (callid) {
1216  ast_channel_callid_set(owner, callid);
1217  }
1218 
1219  ast_channel_tech_set(owner, tech);
1220  ao2_ref(p, +1);
1221  ast_channel_tech_pvt_set(owner, p);
1222 
1224 
1225  if (ast_channel_is_multistream(owner)) {
1226  ast_channel_set_stream_topology(owner, topology);
1227  }
1228 
1229  /* Determine our read/write format and set it on each channel */
1230  fmt = ast_format_cap_get_format(p->reqcap, 0);
1231  if (!fmt) {
1232  ast_channel_tech_pvt_set(owner, NULL);
1233  ao2_ref(p, -1);
1234  ast_channel_unlock(owner);
1235  ast_channel_release(owner);
1236  return NULL;
1237  }
1238 
1239  ast_channel_set_writeformat(owner, fmt);
1240  ast_channel_set_rawwriteformat(owner, fmt);
1241  ast_channel_set_readformat(owner, fmt);
1242  ast_channel_set_rawreadformat(owner, fmt);
1243 
1245 
1246  ast_jb_configure(owner, &p->jb_conf);
1247 
1248  if (ast_channel_cc_params_init(owner, requestor
1249  ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
1250  ast_channel_tech_pvt_set(owner, NULL);
1251  ao2_ref(p, -1);
1252  ast_channel_tech_pvt_set(owner, NULL);
1253  ast_channel_unlock(owner);
1254  ast_channel_release(owner);
1255  return NULL;
1256  }
1257 
1258  p->owner = owner;
1259  ast_channel_unlock(owner);
1260 
1261  chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
1262  exten, context, &id2, owner, 0,
1263  "%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
1264  if (!chan) {
1265  ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
1266  ast_channel_tech_pvt_set(owner, NULL);
1267  ao2_ref(p, -1);
1268  ast_channel_tech_pvt_set(owner, NULL);
1269  ast_channel_release(owner);
1270  return NULL;
1271  }
1272 
1273  if (callid) {
1274  ast_channel_callid_set(chan, callid);
1275  }
1276 
1277  ast_channel_tech_set(chan, tech);
1278  ao2_ref(p, +1);
1279  ast_channel_tech_pvt_set(chan, p);
1280 
1282 
1283  if (ast_channel_is_multistream(chan)) {
1285  p->reqtopology = NULL;
1286  }
1287 
1288  /* Format was already determined when setting up owner */
1289  ast_channel_set_writeformat(chan, fmt);
1290  ast_channel_set_rawwriteformat(chan, fmt);
1291  ast_channel_set_readformat(chan, fmt);
1292  ast_channel_set_rawreadformat(chan, fmt);
1293 
1295 
1296  p->chan = chan;
1297  ast_channel_unlock(chan);
1298 
1299  return owner;
1300 }
int ast_unreal_hangup(struct ast_unreal_pvt *p, struct ast_channel *ast)
Hangup one end (maybe both ends) of an unreal channel derivative.
Definition: core_unreal.c:1018
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
char digit
#define ast_channel_lock(chan)
Definition: channel.h:2945
const char * function
Definition: channel.h:596
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
Music on hold handling.
int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Build the connected line information data frame.
Definition: channel.c:8793
const char *const type
Definition: channel.h:630
Asterisk main include file. File version handling, generic pbx functions.
int ast_unreal_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)
Definition: core_unreal.c:323
static int unreal_colp_stream_topology_request_change(struct ast_unreal_pvt *p, struct ast_channel *ast, const struct ast_stream_topology *topology)
Definition: core_unreal.c:555
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
struct ast_unreal_pvt * ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
Allocate the base unreal struct for a derivative.
Definition: core_unreal.c:1111
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
Structure that contains features information.
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
Definition: stream.c:930
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ast_test_flag(p, flag)
Definition: utils.h:63
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: core_unreal.c:369
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_channel_queryoption(struct ast_channel *channel, int option, void *data, int *datalen, int block)
Checks the value of an option.
Definition: channel.c:7542
struct ast_channel * ast_unreal_new_channels(struct ast_unreal_pvt *p, const struct ast_channel_tech *tech, int semi1_state, int semi2_state, const char *exten, const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
Create the semi1 and semi2 unreal channels.
Definition: core_unreal.c:1162
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#define ast_set_flag(p, flag)
Definition: utils.h:70
static int unreal_queue_frame(struct ast_unreal_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us, int us_locked)
queue a frame onto either the p->owner or p->chan
Definition: core_unreal.c:213
#define LOG_WARNING
Definition: logger.h:274
ast_callid callid
Definition: bridge.h:369
struct ast_channel * owner
Definition: core_unreal.h:93
#define AST_UNREAL_NO_OPTIMIZATION
Definition: core_unreal.h:108
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
struct ast_jb_conf jb_conf
Definition: core_unreal.h:96
struct ast_unreal_pvt * ast_unreal_alloc_stream_topology(size_t size, ao2_destructor_fn destructor, struct ast_stream_topology *topology)
Allocate the base unreal struct for a derivative.
Definition: core_unreal.c:1128
enum ast_control_t38 request_response
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static int unreal_colp_redirect_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
Definition: core_unreal.c:477
Definition of a media format.
Definition: format.c:43
int ast_unreal_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
Definition: core_unreal.c:622
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition: stream.c:848
unsigned int ast_callid
Definition: logger.h:87
struct ast_bridge * ast_channel_internal_bridge(const struct ast_channel *chan)
const char * uniqueid
Definition: channel.h:606
#define ao2_unlock(a)
Definition: astobj2.h:730
char * text
Definition: app_queue.c:1508
struct varshead * ast_channel_varshead(struct ast_channel *chan)
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
struct ast_frame * ast_unreal_read(struct ast_channel *ast)
Definition: core_unreal.c:313
const char * data
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7876
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static unsigned int name_sequence
Definition: core_unreal.c:45
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
struct ast_cc_config_params * ast_channel_get_cc_config_params(struct ast_channel *chan)
Get the CCSS parameters from a channel.
Definition: channel.c:10675
Media Stream API.
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
const char * value
Definition: channel.h:598
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define AST_UNREAL_MOH_INTERCEPT
Definition: core_unreal.h:109
const struct ast_channel_tech * tech
#define ao2_bump(obj)
Definition: astobj2.h:491
struct ast_stream_topology * chan_old_topology
Definition: core_unreal.h:102
struct ast_flags feature_flags
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2373
int ast_unreal_sendtext(struct ast_channel *ast, const char *text)
Definition: core_unreal.c:824
void ast_unreal_destructor(void *vdoomed)
struct ast_unreal_pvt destructor.
Definition: core_unreal.c:1099
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int unreal_queue_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition, const void *data, size_t datalen)
Definition: core_unreal.c:427
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1924
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
General Asterisk PBX channel definitions.
struct ast_channel * chan
Definition: channel.h:595
int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int datalen)
Definition: core_unreal.c:97
const char * ast_channel_accountcode(const struct ast_channel *chan)
int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
Definition: core_unreal.c:318
struct ast_stream * ast_channel_get_default_stream(struct ast_channel *chan, enum ast_media_type type)
Retrieve the default stream of a specific media type on a channel.
#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
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:113
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
Definition: core_unreal.c:295
#define ao2_lock(a)
Definition: astobj2.h:718
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
struct ast_stream_topology * owner_old_topology
Definition: core_unreal.h:101
Core PBX routines and definitions.
int ast_channel_cc_params_init(struct ast_channel *chan, const struct ast_cc_config_params *base_params)
Set up datastore with CCSS parameters for a channel.
Definition: channel.c:10652
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
struct ast_channel * chan
Definition: core_unreal.h:94
int ast_unreal_digit_begin(struct ast_channel *ast, char digit)
Definition: core_unreal.c:779
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
ast_acf_write_fn_t write_fn
Definition: channel.h:594
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
Structure that contains information about a bridge.
Definition: bridge.h:357
char name[0]
Definition: chanvars.h:31
#define LOG_ERROR
Definition: logger.h:285
int ast_bridge_unreal_optimize_out(struct ast_channel *chan, struct ast_channel *peer, struct ast_unreal_pvt *pvt)
Check and optimize out the unreal channels between bridges.
Definition: bridge.c:2968
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct ast_generator * ast_channel_generator(const struct ast_channel *chan)
struct ast_stream_topology * ast_channel_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Set the topology of streams on a channel.
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:592
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
Setup unreal owner and chan channels before initiating call.
Definition: core_unreal.c:870
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_varset for a channel.
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
Push the semi2 unreal channel into a bridge from either member of the unreal pair.
Definition: core_unreal.c:928
char name[AST_MAX_EXTENSION+AST_MAX_CONTEXT+2]
Definition: core_unreal.h:99
void(* ao2_destructor_fn)(void *vdoomed)
Typedef for an object destructor.
Definition: astobj2.h:360
char * value
Definition: chanvars.h:30
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7866
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
const char * ast_channel_peeraccount(const struct ast_channel *chan)
const char * ast_var_full_name(const struct ast_var_t *var)
Definition: chanvars.c:75
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#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
int ast_unreal_answer(struct ast_channel *ast)
Definition: core_unreal.c:254
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define AST_OPTION_CHANNEL_WRITE
Handle channel write data If a channel needs to process the data from a func_channel write operation ...
#define ast_free(a)
Definition: astmm.h:182
struct ast_var_t::@249 entries
Structure to handle passing func_channel_write info to channels via setoption.
Definition: channel.h:590
#define ast_var_assign(name, value)
Definition: chanvars.h:40
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:72
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
Definition: chan_misdn.c:8447
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
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
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3750
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:480
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
int ast_unreal_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
Definition: core_unreal.c:846
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
int ast_unreal_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: core_unreal.c:801
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8389
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
Send an unreal pvt in with no locks held and get all locks.
Definition: core_unreal.c:47
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
const char * ast_channel_language(const struct ast_channel *chan)
void ast_connected_line_copy_to_caller(struct ast_party_caller *dest, const struct ast_party_connected_line *src)
Copy the connected line information to the caller information.
Definition: channel.c:8396
union ast_frame::@263 data
enum ast_frame_type frametype
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
Bridging API.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
Definition: core_unreal.c:166
int ast_channel_stream_topology_changed_externally(struct ast_channel *chan)
Provide notice from a channel that the topology has changed on it as a result of the remote party ren...
Definition: channel.c:11209
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100
const char * uniqueid2
Definition: channel.h:607
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
ast_callid ast_channel_callid(const struct ast_channel *chan)
General jitterbuffer configuration.
Definition: abstract_jb.h:69
const char * ast_channel_parkinglot(const struct ast_channel *chan)
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
int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Build the redirecting id data frame.
Definition: channel.c:9363
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
Copy the source redirecting information to the destination redirecting.
Definition: channel.c:2135
#define AST_OPTION_T38_STATE
const char * ast_channel_musicclass(const struct ast_channel *chan)
jack_status_t status
Definition: app_jack.c:146
void ast_party_dialed_copy(struct ast_party_dialed *dest, const struct ast_party_dialed *src)
Copy the source dialed party information to the destination dialed party.
Definition: channel.c:1936
Unreal channel derivative framework.