Asterisk - The Open Source Telephony Project GIT-master-2de1a68
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 <rmudgett@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief Unreal channel derivatives framework for channel drivers like local channels.
22 *
23 * \author Richard Mudgett <rmudgett@digium.com>
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"
40#include "asterisk/astobj2.h"
41#include "asterisk/bridge.h"
43#include "asterisk/stream.h"
44
45static unsigned int name_sequence = 0;
46
47void 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) {
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 */
97int 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
156setoption_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 */
166int 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 */
213static 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
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) {
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) {
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 */
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 */
295static 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) {
306 } else if (ast == p->chan) {
308 }
309
310 return res;
311}
312
314{
315 return &ast_null_frame;
316}
317
318int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
319{
320 return ast_unreal_write_stream(ast, -1, f);
321}
322
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
369int 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 */
427static 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) {
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 */
477static 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 */
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 */
555static 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
588 }
589 }
590
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
622int 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;
656 ast_moh_stop(ast);
657 break;
658 }
659 res = unreal_queue_indicate(p, ast, condition, data, datalen);
660 break;
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;
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 */
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 */
738 ast_unreal_lock_all(p, &chan, &owner);
739
740 if (owner) {
743 }
744
745 if (chan) {
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);
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
801int 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);
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
824int 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
846int 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
870void 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
928int 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;
935
937 bridge_callid = bridge->callid;
939
940 {
942 p = ast_channel_tech_pvt(ast);
943 if (!p) {
944 return -1;
945 }
946 ao2_ref(p, +1);
947 }
948
949 {
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
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 if (ast == p->chan) {
1040 /* Outgoing side is hanging up. */
1042 p->chan = NULL;
1043 if (p->owner) {
1044 const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
1045
1046 if (status) {
1048 pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
1049 }
1051 }
1052 } else {
1053 /* Owner side is hanging up. */
1054 p->owner = NULL;
1055 if (p->chan) {
1056 if (cause == AST_CAUSE_ANSWERED_ELSEWHERE) {
1058 ast_debug(2, "%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
1060 }
1062 /*
1063 * Need to actually hangup p->chan since nothing else is taking
1064 * care of it.
1065 */
1066 hangup_chan = 1;
1067 } else {
1069 }
1070 }
1071 }
1072
1073 /* this is one of our locked channels, doesn't matter which */
1075 ao2_ref(p, -1);
1076
1077unreal_hangup_cleanup:
1078 ao2_unlock(p);
1079 if (owner) {
1080 ast_channel_unlock(owner);
1081 ast_channel_unref(owner);
1082 }
1083 if (chan) {
1084 ast_channel_unlock(chan);
1085 if (hangup_chan) {
1086 ast_hangup(chan);
1087 }
1088 ast_channel_unref(chan);
1089 }
1090
1091 /* leave with the channel locked that came in */
1092 ast_channel_lock(ast);
1093
1094 return res;
1095}
1096
1097void ast_unreal_destructor(void *vdoomed)
1098{
1099 struct ast_unreal_pvt *doomed = vdoomed;
1100
1101 ao2_cleanup(doomed->reqcap);
1102 doomed->reqcap = NULL;
1104 doomed->reqtopology = NULL;
1107}
1108
1109struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
1110{
1111 struct ast_stream_topology *topology;
1112 struct ast_unreal_pvt *unreal;
1113
1115 if (!topology) {
1116 return NULL;
1117 }
1118
1119 unreal = ast_unreal_alloc_stream_topology(size, destructor, topology);
1120
1121 ast_stream_topology_free(topology);
1122
1123 return unreal;
1124}
1125
1127{
1128 struct ast_unreal_pvt *unreal;
1129
1130 static const struct ast_jb_conf jb_conf = {
1131 .flags = 0,
1132 .max_size = -1,
1133 .resync_threshold = -1,
1134 .impl = "",
1135 .target_extra = -1,
1136 };
1137
1138 unreal = ao2_alloc(size, destructor);
1139 if (!unreal) {
1140 return NULL;
1141 }
1142
1143 unreal->reqtopology = ast_stream_topology_clone(topology);
1144 if (!unreal->reqtopology) {
1145 ao2_ref(unreal, -1);
1146 return NULL;
1147 }
1148
1149 unreal->reqcap = ast_stream_topology_get_formats(topology);
1150 if (!unreal->reqcap) {
1151 ao2_ref(unreal, -1);
1152 return NULL;
1153 }
1154
1155 memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
1156
1157 return unreal;
1158}
1159
1161 const struct ast_channel_tech *tech, int semi1_state, int semi2_state,
1162 const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
1163 const struct ast_channel *requestor, ast_callid callid)
1164{
1165 struct ast_channel *owner;
1166 struct ast_channel *chan;
1167 RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
1168 struct ast_assigned_ids id1 = {NULL, NULL};
1169 struct ast_assigned_ids id2 = {NULL, NULL};
1170 int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
1171 int i;
1172 struct ast_stream_topology *chan_topology;
1173 struct ast_stream *stream;
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 second channel, as we can't
1192 * share a single one between both.
1193 */
1194 chan_topology = ast_stream_topology_clone(p->reqtopology);
1195 if (!chan_topology) {
1196 return NULL;
1197 }
1198
1199 for (i = 0; i < ast_stream_topology_get_count(chan_topology); ++i) {
1200 stream = ast_stream_topology_get_stream(chan_topology, i);
1201 /* We need to make sure that the ;2 channel has the opposite stream topology
1202 * of the first channel if the stream is one-way. I.e. if the first channel
1203 * is recvonly, the second channel has to be sendonly and vice versa.
1204 */
1207 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
1209 }
1210 }
1211
1212 /*
1213 * Allocate two new Asterisk channels
1214 *
1215 * Make sure that the ;2 channel gets the same linkedid as ;1.
1216 * You can't pass linkedid to both allocations since if linkedid
1217 * isn't set, then each channel will generate its own linkedid.
1218 */
1219 owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
1220 exten, context, &id1, requestor, 0,
1221 "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
1222 if (!owner) {
1223 ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
1224 ast_stream_topology_free(chan_topology);
1225 return NULL;
1226 }
1227
1228 if (callid) {
1229 ast_channel_callid_set(owner, callid);
1230 }
1231
1232 ast_channel_tech_set(owner, tech);
1233 ao2_ref(p, +1);
1234 ast_channel_tech_pvt_set(owner, p);
1235
1237
1238 if (ast_channel_is_multistream(owner)) {
1240 p->reqtopology = NULL;
1241 }
1242
1243 /* Determine our read/write format and set it on each channel */
1244 fmt = ast_format_cap_get_format(p->reqcap, 0);
1245 if (!fmt) {
1247 ao2_ref(p, -1);
1248 ast_channel_unlock(owner);
1249 ast_channel_release(owner);
1250 return NULL;
1251 }
1252
1253 ast_channel_set_writeformat(owner, fmt);
1255 ast_channel_set_readformat(owner, fmt);
1257
1259
1260 ast_jb_configure(owner, &p->jb_conf);
1261
1262 if (ast_channel_cc_params_init(owner, requestor
1263 ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
1265 ao2_ref(p, -1);
1267 ast_channel_unlock(owner);
1268 ast_channel_release(owner);
1269 return NULL;
1270 }
1271
1272 p->owner = owner;
1273 ast_channel_unlock(owner);
1274
1275 chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
1276 exten, context, &id2, owner, 0,
1277 "%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
1278 if (!chan) {
1279 ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
1281 ao2_ref(p, -1);
1283 ast_channel_release(owner);
1284 return NULL;
1285 }
1286
1287 if (callid) {
1288 ast_channel_callid_set(chan, callid);
1289 }
1290
1291 ast_channel_tech_set(chan, tech);
1292 ao2_ref(p, +1);
1293 ast_channel_tech_pvt_set(chan, p);
1294
1296
1297 if (ast_channel_is_multistream(chan)) {
1298 ast_channel_set_stream_topology(chan, chan_topology);
1299 }
1300
1301 /* Format was already determined when setting up owner */
1302 ast_channel_set_writeformat(chan, fmt);
1304 ast_channel_set_readformat(chan, fmt);
1306
1308
1309 p->chan = chan;
1310 ast_channel_unlock(chan);
1311
1312 return owner;
1313}
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
char digit
jack_status_t status
Definition: app_jack.c:146
char * text
Definition: app_queue.c:1639
ast_mutex_t lock
Definition: app_sla.c:331
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void(* ao2_destructor_fn)(void *vdoomed)
Typedef for an object destructor.
Definition: astobj2.h:358
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
Bridging API.
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
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:1878
#define ast_bridge_lock(bridge)
Lock the bridge.
Definition: bridge.h:470
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:590
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:2920
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683
Internal Asterisk hangup causes.
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
static int answer(void *data)
Definition: chan_pjsip.c:683
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_bridge * ast_channel_internal_bridge(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.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1150
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10563
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
const char * ast_channel_musicclass(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
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:7441
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
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:10450
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1139
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2368
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_parkinglot(const struct ast_channel *chan)
const char * ast_channel_peeraccount(const struct ast_channel *chan)
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1166
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
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
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
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:9267
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
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:8696
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
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.
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:11007
struct ast_generator * ast_channel_generator(const struct ast_channel *chan)
const char * ast_channel_language(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:8292
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
Definition: channel.h:1029
#define AST_CHAN_WRITE_INFO_T_VERSION
ast_chan_write_info_t version. Must be incremented if structure is changed
Definition: channel.h:591
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
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:8299
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_channel_is_multistream(struct ast_channel *chan)
Determine if a channel is multi-stream capable.
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
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:10473
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_RINGING
Definition: channelstate.h:41
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7385
#define ast_var_assign(name, value)
Definition: chanvars.h:40
const char * ast_var_full_name(const struct ast_var_t *var)
Definition: chanvars.c:75
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
@ AST_MEDIA_TYPE_IMAGE
Definition: codec.h:34
int ast_unreal_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Definition: core_unreal.c:801
int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int datalen)
Definition: core_unreal.c:97
static int unreal_colp_redirect_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
Definition: core_unreal.c:477
int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
Definition: core_unreal.c:166
int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: core_unreal.c:369
int ast_unreal_digit_begin(struct ast_channel *ast, char digit)
Definition: core_unreal.c:779
int ast_unreal_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
Definition: core_unreal.c:846
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_unreal_destructor(void *vdoomed)
struct ast_unreal_pvt destructor.
Definition: core_unreal.c:1097
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
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
static unsigned int name_sequence
Definition: core_unreal.c:45
int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
Definition: core_unreal.c:318
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:1109
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:1126
int ast_unreal_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
Definition: core_unreal.c:622
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
int ast_unreal_sendtext(struct ast_channel *ast, const char *text)
Definition: core_unreal.c:824
static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
Definition: core_unreal.c:295
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
int ast_unreal_answer(struct ast_channel *ast)
Definition: core_unreal.c:254
int ast_unreal_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)
Definition: core_unreal.c:323
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
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:1160
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
struct ast_frame * ast_unreal_read(struct ast_channel *ast)
Definition: core_unreal.c:313
Unreal channel derivative framework.
#define AST_UNREAL_IS_OUTBOUND(a, b)
Definition: core_unreal.h:105
#define AST_UNREAL_MOH_INTERCEPT
Definition: core_unreal.h:109
#define AST_UNREAL_NO_OPTIMIZATION
Definition: core_unreal.h:108
#define AST_UNREAL_CARETAKER_THREAD
Definition: core_unreal.h:107
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_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
@ AST_T38_REQUEST_PARMS
@ AST_T38_TERMINATED
@ AST_T38_NEGOTIATED
#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_OPTION_T38_STATE
@ AST_FRAME_VIDEO
@ AST_FRAME_HTML
@ AST_FRAME_DTMF_END
@ AST_FRAME_DTMF_BEGIN
@ AST_FRAME_VOICE
@ AST_FRAME_CONTROL
@ AST_FRAME_TEXT
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_T38_PARAMETERS
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HOLD
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_MASQUERADE_NOTIFY
@ AST_CONTROL_PVT_CAUSE_CODE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int ast_callid
#define LOG_ERROR
#define LOG_WARNING
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
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:757
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
Music on hold handling.
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:7765
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7775
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
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.
#define NULL
Definition: resample.c:96
Media Stream API.
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
struct ast_stream * ast_stream_alloc(const char *name, enum ast_media_type type)
Create a new media stream representation.
Definition: stream.c:233
@ AST_STREAM_STATE_RECVONLY
Set when the stream is receiving media only.
Definition: stream.h:90
@ AST_STREAM_STATE_SENDONLY
Set when the stream is sending media only.
Definition: stream.h:86
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 ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
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
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
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
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
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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
const char * uniqueid2
Definition: channel.h:606
const char * uniqueid
Definition: channel.h:605
Structure that contains features information.
struct ast_flags feature_flags
Structure that contains information about a bridge.
Definition: bridge.h:349
ast_callid callid
Definition: bridge.h:361
Structure to handle passing func_channel_write info to channels via setoption.
Definition: channel.h:589
ast_acf_write_fn_t write_fn
Definition: channel.h:593
struct ast_channel * chan
Definition: channel.h:594
const char * value
Definition: channel.h:597
const char * function
Definition: channel.h:595
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
const char *const type
Definition: channel.h:629
Main Channel structure associated with a channel.
struct ast_filestream * stream
struct ast_bridge * bridge
char exten[AST_MAX_EXTENSION]
const char * data
const struct ast_channel_tech * tech
struct ast_flags flags
enum ast_control_t38 request_response
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
General jitterbuffer configuration.
Definition: abstract_jb.h:70
The base pvt structure for local channel derivatives.
Definition: core_unreal.h:91
struct ast_jb_conf jb_conf
Definition: core_unreal.h:96
struct ast_stream_topology * chan_old_topology
Definition: core_unreal.h:102
struct ast_format_cap * reqcap
Definition: core_unreal.h:95
struct ast_channel * chan
Definition: core_unreal.h:94
char name[AST_MAX_EXTENSION+AST_MAX_CONTEXT+2]
Definition: core_unreal.h:99
struct ast_channel * owner
Definition: core_unreal.h:93
struct ast_stream_topology * owner_old_topology
Definition: core_unreal.h:101
struct ast_stream_topology * reqtopology
Definition: core_unreal.h:100
char name[0]
Definition: chanvars.h:31
char * value
Definition: chanvars.h:30
struct ast_var_t::@211 entries
long resync_threshold
Definition: jitterbuf.h:70
#define ast_test_flag(p, flag)
Definition: utils.h:63
#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:941
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70