Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
features.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2012, Digium, Inc.
5 * Copyright (C) 2012, Russell Bryant
6 *
7 * Mark Spencer <markster@digium.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20/*! \file
21 *
22 * \brief Routines implementing call features as call pickup, parking and transfer
23 *
24 * \author Mark Spencer <markster@digium.com>
25 */
26
27/*! \li \ref features.c uses the configuration file \ref features.conf
28 * \addtogroup configuration_file Configuration Files
29 */
30
31/*!
32 * \page features.conf features.conf
33 * \verbinclude features.conf.sample
34 */
35
36/*** MODULEINFO
37 <support_level>core</support_level>
38 ***/
39
40#include "asterisk.h"
41
42#include "asterisk/_private.h"
43#include "features_config.h"
44
45#include <pthread.h>
46#include <signal.h>
47#include <sys/time.h>
48#include <signal.h>
49#include <netinet/in.h>
50
51#include "asterisk/lock.h"
52#include "asterisk/file.h"
53#include "asterisk/channel.h"
54#include "asterisk/pbx.h"
55#include "asterisk/causes.h"
56#include "asterisk/module.h"
57#include "asterisk/translate.h"
58#include "asterisk/app.h"
59#include "asterisk/say.h"
60#include "asterisk/features.h"
62#include "asterisk/config.h"
63#include "asterisk/cli.h"
64#include "asterisk/manager.h"
65#include "asterisk/utils.h"
67#include "asterisk/audiohook.h"
69#include "asterisk/astobj2.h"
70#include "asterisk/test.h"
71#include "asterisk/bridge.h"
75#include "asterisk/stasis.h"
79#include "asterisk/stream.h"
80
81/*** DOCUMENTATION
82 <application name="Bridge" language="en_US">
83 <since>
84 <version>1.6.0</version>
85 </since>
86 <synopsis>
87 Bridge two channels.
88 </synopsis>
89 <syntax>
90 <parameter name="channel" required="true">
91 <para>The current channel is bridged to the channel
92 identified by the channel name, channel name prefix, or channel
93 uniqueid.</para>
94 </parameter>
95 <parameter name="options">
96 <optionlist>
97 <option name="p">
98 <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
99 </option>
100 <option name="F" argsep="^">
101 <argument name="context" required="false" />
102 <argument name="exten" required="false" />
103 <argument name="priority" required="true" />
104 <para>When the bridger hangs up, transfer the <emphasis>bridged</emphasis> party
105 to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
106 <note>
107 <para>Any channel variables you want the called channel to inherit from the caller channel must be
108 prefixed with one or two underbars ('_').</para>
109 </note>
110 <note>
111 <para>This option will override the 'x' option</para>
112 </note>
113 </option>
114 <option name="F">
115 <para>When the bridger hangs up, transfer the <emphasis>bridged</emphasis> party
116 to the next priority of the current extension and <emphasis>start</emphasis> execution
117 at that location.</para>
118 <note>
119 <para>Any channel variables you want the called channel to inherit from the caller channel must be
120 prefixed with one or two underbars ('_').</para>
121 </note>
122 <note>
123 <para>Using this option from a or GoSub() might not make sense as there would be no return points.</para>
124 </note>
125 <note>
126 <para>This option will override the 'x' option</para>
127 </note>
128 </option>
129
130 <option name="h">
131 <para>Allow the called party to hang up by sending the
132 <replaceable>*</replaceable> DTMF digit.</para>
133 </option>
134 <option name="H">
135 <para>Allow the calling party to hang up by pressing the
136 <replaceable>*</replaceable> DTMF digit.</para>
137 </option>
138 <option name="k">
139 <para>Allow the called party to enable parking of the call by sending
140 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
141 </option>
142 <option name="K">
143 <para>Allow the calling party to enable parking of the call by sending
144 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
145 </option>
146 <option name="L(x[:y][:z])">
147 <para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
148 when <replaceable>y</replaceable> ms are left. Repeat the warning every
149 <replaceable>z</replaceable> ms. The following special variables can be
150 used with this option:</para>
151 <variablelist>
152 <variable name="LIMIT_PLAYAUDIO_CALLER">
153 <para>Play sounds to the caller. yes|no (default yes)</para>
154 </variable>
155 <variable name="LIMIT_PLAYAUDIO_CALLEE">
156 <para>Play sounds to the callee. yes|no</para>
157 </variable>
158 <variable name="LIMIT_TIMEOUT_FILE">
159 <para>File to play when time is up.</para>
160 </variable>
161 <variable name="LIMIT_CONNECT_FILE">
162 <para>File to play when call begins.</para>
163 </variable>
164 <variable name="LIMIT_WARNING_FILE">
165 <para>File to play as warning if <replaceable>y</replaceable> is
166 defined. The default is to say the time remaining.</para>
167 </variable>
168 </variablelist>
169 </option>
170 <option name="n">
171 <para>Do not answer the channel automatically before bridging.</para>
172 <para>Additionally, to prevent a bridged channel (the target of the Bridge application)
173 from answering, the <literal>BRIDGE_NOANSWER</literal> variable can be set to inhibit
174 answering.</para>
175 </option>
176 <option name="S(x)">
177 <para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
178 </option>
179 <option name="t">
180 <para>Allow the called party to transfer the calling party by sending the
181 DTMF sequence defined in <filename>features.conf</filename>.</para>
182 </option>
183 <option name="T">
184 <para>Allow the calling party to transfer the called party by sending the
185 DTMF sequence defined in <filename>features.conf</filename>.</para>
186 </option>
187 <option name="w">
188 <para>Allow the called party to enable recording of the call by sending
189 the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
190 </option>
191 <option name="W">
192 <para>Allow the calling party to enable recording of the call by sending
193 the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
194 </option>
195 <option name="x">
196 <para>Cause the called party to be hung up after the bridge, instead of being
197 restarted in the dialplan.</para>
198 </option>
199 </optionlist>
200 </parameter>
201 </syntax>
202 <description>
203 <para>Allows the ability to bridge two channels via the dialplan.</para>
204 <para>This application sets the following channel variable upon completion:</para>
205 <variablelist>
206 <variable name="BRIDGERESULT">
207 <para>The result of the bridge attempt as a text string.</para>
208 <value name="SUCCESS" />
209 <value name="FAILURE" />
210 <value name="LOOP" />
211 <value name="NONEXISTENT" />
212 </variable>
213 </variablelist>
214 </description>
215 <see-also>
216 <ref type="manager">Bridge</ref>
217 <ref type="managerEvent">BridgeCreate</ref>
218 <ref type="managerEvent">BridgeEnter</ref>
219 </see-also>
220 </application>
221 <manager name="Bridge" language="en_US">
222 <since>
223 <version>1.6.0</version>
224 </since>
225 <synopsis>
226 Bridge two channels already in the PBX.
227 </synopsis>
228 <syntax>
229 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
230 <parameter name="Channel1" required="true">
231 <para>Channel to Bridge to Channel2.</para>
232 </parameter>
233 <parameter name="Channel2" required="true">
234 <para>Channel to Bridge to Channel1.</para>
235 </parameter>
236 <parameter name="Tone">
237 <para>Play courtesy tone to Channel 2.</para>
238 <enumlist>
239 <enum name="no" />
240 <enum name="Channel1" />
241 <enum name="Channel2" />
242 <enum name="Both" />
243 </enumlist>
244 </parameter>
245 </syntax>
246 <description>
247 <para>Bridge together two channels already in the PBX.</para>
248 </description>
249 <see-also>
250 <ref type="application">Bridge</ref>
251 <ref type="managerEvent">BridgeCreate</ref>
252 <ref type="managerEvent">BridgeEnter</ref>
253 <ref type="manager">BridgeDestroy</ref>
254 <ref type="manager">BridgeInfo</ref>
255 <ref type="manager">BridgeKick</ref>
256 <ref type="manager">BridgeList</ref>
257 </see-also>
258 </manager>
259 ***/
260
261typedef enum {
262 FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
263 FEATURE_INTERPRET_DO, /* Used by feature_interpret */
264 FEATURE_INTERPRET_CHECK, /* Used by feature_check */
266
268 /*! Channel's feature flags. */
270 /*! Bridge peer's feature flags. */
272};
273
274static void *dial_features_duplicate(void *data)
275{
276 struct ast_dial_features *df = data, *df_copy;
277
278 if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
279 return NULL;
280 }
281
282 memcpy(df_copy, df, sizeof(*df));
283
284 return df_copy;
285}
286
288 .type = "dial-features",
289 .destroy = ast_free_ptr,
290 .duplicate = dial_features_duplicate,
291};
292
293/*!
294 * \internal
295 * \brief Set the features datastore if it doesn't exist.
296 *
297 * \param chan Channel to add features datastore
298 * \param my_features The channel's feature flags
299 * \param peer_features The channel's bridge peer feature flags
300 *
301 * \retval TRUE if features datastore already existed.
302 */
303static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
304{
305 struct ast_datastore *datastore;
306 struct ast_dial_features *dialfeatures;
307
308 ast_channel_lock(chan);
310 ast_channel_unlock(chan);
311 if (datastore) {
312 /* Already exists. */
313 return 1;
314 }
315
316 /* Create a new datastore with specified feature flags. */
318 if (!datastore) {
319 ast_log(LOG_WARNING, "Unable to create channel features datastore.\n");
320 return 0;
321 }
322 dialfeatures = ast_calloc(1, sizeof(*dialfeatures));
323 if (!dialfeatures) {
324 ast_log(LOG_WARNING, "Unable to allocate memory for feature flags.\n");
325 ast_datastore_free(datastore);
326 return 0;
327 }
331 datastore->data = dialfeatures;
332 ast_channel_lock(chan);
333 ast_channel_datastore_add(chan, datastore);
334 ast_channel_unlock(chan);
335 return 0;
336}
337
339{
343 unsigned int return_to_pbx:1;
344};
345
346static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
347{
349
350 if (ast_test_flag(&config->features_caller, AST_FEATURE_DTMF_MASK)) {
352 }
353 if (ast_test_flag(&config->features_callee, AST_FEATURE_DTMF_MASK)) {
355 }
356
358 RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
359
360 ast_channel_lock(chan);
361 applicationmap = ast_get_chan_applicationmap(chan);
362 ast_channel_unlock(chan);
363
364 if (!applicationmap) {
365 return;
366 }
367
368 /* If an applicationmap exists for this channel at all, then the channel needs the DTMF flag set */
370 }
371}
372
373void ast_channel_log(char *title, struct ast_channel *chan);
374
375void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
376{
377 ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long) chan);
378 ast_log(LOG_NOTICE, "CHAN: name: %s; appl: %s; data: %s; contxt: %s; exten: %s; pri: %d;\n",
381 ast_log(LOG_NOTICE, "CHAN: acctcode: %s; dialcontext: %s; amaflags: %x;\n",
383 ast_log(LOG_NOTICE, "CHAN: masq: %p; masqr: %p; uniqueID: %s; linkedID:%s\n",
386 if (ast_channel_masqr(chan)) {
387 ast_log(LOG_NOTICE, "CHAN: masquerading as: %s; cdr: %p;\n",
389 }
390
391 ast_log(LOG_NOTICE, "===== done ====\n");
392}
393
394static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
395{
396 const char *feature;
397
398 if (ast_strlen_zero(features)) {
399 return;
400 }
401
402 for (feature = features; *feature; feature++) {
403 struct ast_flags *party;
404
405 if (isupper(*feature)) {
406 party = &config->features_caller;
407 } else {
408 party = &config->features_callee;
409 }
410
411 switch (tolower(*feature)) {
412 case 't' :
414 break;
415 case 'k' :
417 break;
418 case 'h' :
420 break;
421 case 'w' :
423 break;
424 case 'x' :
426 break;
427 default :
428 ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
429 break;
430 }
431 }
432}
433
434static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
435{
436 if (add_features_datastore(caller, &config->features_caller, &config->features_callee)) {
437 /*
438 * If we don't return here, then when we do a builtin_atxfer we
439 * will copy the disconnect flags over from the atxfer to the
440 * callee (Party C).
441 */
442 return;
443 }
444
445 add_features_datastore(callee, &config->features_callee, &config->features_caller);
446}
447
449{
450 if (config->end_sound) {
451 ast_string_field_set(limits, duration_sound, config->end_sound);
452 }
453
454 if (config->warning_sound) {
455 ast_string_field_set(limits, warning_sound, config->warning_sound);
456 }
457
458 if (config->start_sound) {
459 ast_string_field_set(limits, connect_sound, config->start_sound);
460 }
461
462 limits->frequency = config->warning_freq;
463 limits->warning = config->play_warning;
464}
465
466/*!
467 * \internal brief Setup limit hook structures on calls that need limits
468 *
469 * \param config ast_bridge_config which provides the limit data
470 * \param caller_limits pointer to an ast_bridge_features_limits struct which will store the caller side limits
471 * \param callee_limits pointer to an ast_bridge_features_limits struct which will store the callee side limits
472 */
473static void bridge_config_set_limits(struct ast_bridge_config *config, struct ast_bridge_features_limits *caller_limits, struct ast_bridge_features_limits *callee_limits)
474{
475 if (ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING)) {
477 }
478
479 if (ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING)) {
481 }
482
483 caller_limits->duration = config->timelimit;
484 callee_limits->duration = config->timelimit;
485}
486
487/*!
488 * \internal
489 * \brief Send the peer channel on its way on bridge start failure.
490 * \since 12.0.0
491 *
492 * \param chan Chan to put into autoservice.
493 * \param peer Chan to send to after bridge goto or run hangup handlers and hangup.
494 */
495static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel *peer)
496{
498 || ast_pbx_start(peer)) {
500 }
501}
502
503static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config,
504 struct ast_bridge_features *chan_features, struct ast_bridge_features *peer_features, int noanswer)
505{
506 int res;
507 SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
508
510 add_features_datastores(chan, peer, config);
511
512 /*
513 * This is an interesting case. One example is if a ringing
514 * channel gets redirected to an extension that picks up a
515 * parked call. This will make sure that the call taken out of
516 * parking gets told that the channel it just got bridged to is
517 * still ringing.
518 */
522 }
523
525
526 /* Answer if need be */
527
528 res = 0;
529
530 if (noanswer) {
531 ast_debug(1, "Skipping answer on %s due to no answer directive\n", ast_channel_name(chan));
532 } else if (ast_channel_state(chan) != AST_STATE_UP) {
533 ast_debug(1, "Answering channel for bridge: %s\n", ast_channel_name(chan));
534 res = ast_raw_answer_with_stream_topology(chan, config->answer_topology);
535 if (res != 0) {
536 return -1;
537 }
538 }
539
540
541#ifdef FOR_DEBUG
542 /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
543 ast_channel_log("Pre-bridge CHAN Channel info", chan);
544 ast_channel_log("Pre-bridge PEER Channel info", peer);
545#endif
546
547 res = 0;
548 ast_channel_lock(chan);
550 res |= ast_bridge_features_ds_append(chan, &config->features_caller);
551 ast_channel_unlock(chan);
552 ast_channel_lock(peer);
554 res |= ast_bridge_features_ds_append(peer, &config->features_callee);
555 ast_channel_unlock(peer);
556
557 if (res) {
558 return -1;
559 }
560
561 if (config->timelimit) {
562 struct ast_bridge_features_limits call_duration_limits_chan;
563 struct ast_bridge_features_limits call_duration_limits_peer;
564 int abandon_call = 0; /* TRUE if set limits fails so we can abandon the call. */
565
566 if (ast_bridge_features_limits_construct(&call_duration_limits_chan)) {
567 ast_log(LOG_ERROR, "Could not construct caller duration limits. Bridge canceled.\n");
568
569 return -1;
570 }
571
572 if (ast_bridge_features_limits_construct(&call_duration_limits_peer)) {
573 ast_log(LOG_ERROR, "Could not construct callee duration limits. Bridge canceled.\n");
574 ast_bridge_features_limits_destroy(&call_duration_limits_chan);
575
576 return -1;
577 }
578
579 bridge_config_set_limits(config, &call_duration_limits_chan, &call_duration_limits_peer);
580
581 if (ast_bridge_features_set_limits(chan_features, &call_duration_limits_chan, 0)) {
582 abandon_call = 1;
583 }
584 if (ast_bridge_features_set_limits(peer_features, &call_duration_limits_peer, 0)) {
585 abandon_call = 1;
586 }
587
588 /* At this point we are done with the limits structs since they have been copied to the individual feature sets. */
589 ast_bridge_features_limits_destroy(&call_duration_limits_chan);
590 ast_bridge_features_limits_destroy(&call_duration_limits_peer);
591
592 if (abandon_call) {
593 ast_log(LOG_ERROR, "Could not set duration limits on one or more sides of the call. Bridge canceled.\n");
594 return -1;
595 }
596 }
597
598 return 0;
599}
600
601int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags)
602{
603 int res;
604 struct ast_bridge *bridge;
605 struct ast_bridge_features chan_features;
606 struct ast_bridge_features *peer_features;
607 const char *value;
608 int noanswer;
609 SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
610
611 /* Setup features. */
612 res = ast_bridge_features_init(&chan_features);
613 peer_features = ast_bridge_features_new();
614 if (res || !peer_features) {
615 ast_bridge_features_destroy(peer_features);
616 ast_bridge_features_cleanup(&chan_features);
617 bridge_failed_peer_goto(chan, peer);
618 return -1;
619 }
620
621 ast_channel_lock(chan);
622 value = pbx_builtin_getvar_helper(chan, "BRIDGE_NOANSWER");
623 noanswer = !ast_strlen_zero(value) ? 1 : 0;
624 ast_channel_unlock(chan);
625
626 if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features, noanswer)) {
627 ast_bridge_features_destroy(peer_features);
628 ast_bridge_features_cleanup(&chan_features);
629 bridge_failed_peer_goto(chan, peer);
630 return -1;
631 }
632
633 /* Create bridge */
634 bridge = ast_bridge_basic_new();
635 if (!bridge) {
636 ast_bridge_features_destroy(peer_features);
637 ast_bridge_features_cleanup(&chan_features);
638 bridge_failed_peer_goto(chan, peer);
639 return -1;
640 }
641
642 ast_bridge_basic_set_flags(bridge, flags);
643
644 /* Put peer into the bridge */
645 if (ast_bridge_impart(bridge, peer, NULL, peer_features,
647 ast_bridge_destroy(bridge, 0);
648 ast_bridge_features_cleanup(&chan_features);
649 bridge_failed_peer_goto(chan, peer);
650 return -1;
651 }
652
653 /* Join bridge */
654 ast_bridge_join(bridge, chan, NULL, &chan_features, NULL,
656
657 /*
658 * If the bridge was broken for a hangup that isn't real, then
659 * don't run the h extension, because the channel isn't really
660 * hung up. This should really only happen with
661 * AST_SOFTHANGUP_ASYNCGOTO.
662 */
663 res = -1;
664 ast_channel_lock(chan);
666 res = 0;
667 }
668 ast_channel_unlock(chan);
669
670 ast_bridge_features_cleanup(&chan_features);
671
672 if (res && config->end_bridge_callback) {
673 config->end_bridge_callback(config->end_bridge_callback_data);
674 }
675
676 return res;
677}
678
679/*!
680 * \brief bridge the call and set CDR
681 *
682 * \param chan The bridge considers this channel the caller.
683 * \param peer The bridge considers this channel the callee.
684 * \param config Configuration for this bridge.
685 *
686 * Set start time, check for two channels,check if monitor on
687 * check for feature activation, create new CDR
688 * \return res on success.
689 * \retval -1 on failure to bridge.
690 */
691int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
692{
693 return ast_bridge_call_with_flags(chan, peer, config, 0);
694}
695
701};
702
703static enum play_tone_action parse_playtone(const char *playtone_val)
704{
705 if (ast_strlen_zero(playtone_val) || ast_false(playtone_val)) {
706 return PLAYTONE_NONE;
707 } if (!strcasecmp(playtone_val, "channel1")) {
708 return PLAYTONE_CHANNEL1;
709 } else if (!strcasecmp(playtone_val, "channel2") || ast_true(playtone_val)) {
710 return PLAYTONE_CHANNEL2;
711 } else if (!strcasecmp(playtone_val, "both")) {
712 return PLAYTONE_BOTH;
713 } else {
714 /* Invalid input. Assume none */
715 return PLAYTONE_NONE;
716 }
717}
718
719/*!
720 * \brief Bridge channels together
721 * \param s
722 * \param m
723 *
724 * Make sure valid channels were specified,
725 * send errors if any of the channels could not be found/locked, answer channels if needed,
726 * create the placeholder channels and grab the other channels
727 * make the channels compatible, send error if we fail doing so
728 * setup the bridge thread object and start the bridge.
729 *
730 * \retval 0
731 */
732static int action_bridge(struct mansession *s, const struct message *m)
733{
734 const char *channela = astman_get_header(m, "Channel1");
735 const char *channelb = astman_get_header(m, "Channel2");
737 RAII_VAR(struct ast_channel *, chana, NULL, ao2_cleanup);
738 RAII_VAR(struct ast_channel *, chanb, NULL, ao2_cleanup);
739 const char *chana_exten;
740 const char *chana_context;
741 int chana_priority;
742 const char *chanb_exten;
743 const char *chanb_context;
744 int chanb_priority;
745 struct ast_bridge *bridge;
746 char buf[256];
747 RAII_VAR(struct ast_features_xfer_config *, xfer_cfg_a, NULL, ao2_cleanup);
748 RAII_VAR(struct ast_features_xfer_config *, xfer_cfg_b, NULL, ao2_cleanup);
749
750 /* make sure valid channels were specified */
751 if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
752 astman_send_error(s, m, "Missing channel parameter in request");
753 return 0;
754 }
755
756 ast_debug(1, "Performing Bridge action on %s and %s\n", channela, channelb);
757
758 /* Start with chana */
759 chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
760 if (!chana) {
761 snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela);
762 astman_send_error(s, m, buf);
763 return 0;
764 }
765 ast_channel_lock(chana);
766 xfer_cfg_a = ast_get_chan_features_xfer_config(chana);
767 chana_exten = ast_strdupa(ast_channel_exten(chana));
768 chana_context = ast_strdupa(ast_channel_context(chana));
769 chana_priority = ast_channel_priority(chana);
771 chana_priority++;
772 }
773 ast_channel_unlock(chana);
774
775 chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
776 if (!chanb) {
777 snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb);
778 astman_send_error(s, m, buf);
779 return 0;
780 }
781 ast_channel_lock(chanb);
782 xfer_cfg_b = ast_get_chan_features_xfer_config(chanb);
783 chanb_exten = ast_strdupa(ast_channel_exten(chanb));
784 chanb_context = ast_strdupa(ast_channel_context(chanb));
785 chanb_priority = ast_channel_priority(chanb);
787 chanb_priority++;
788 }
789 ast_channel_unlock(chanb);
790
791 bridge = ast_bridge_basic_new();
792 if (!bridge) {
793 astman_send_error(s, m, "Unable to create bridge\n");
794 return 0;
795 }
796
797 ast_bridge_set_after_goto(chana, chana_context, chana_exten, chana_priority);
798 if (ast_bridge_add_channel(bridge, chana, NULL, playtone & PLAYTONE_CHANNEL1, xfer_cfg_a ? xfer_cfg_a->xfersound : NULL)) {
799 snprintf(buf, sizeof(buf), "Unable to add Channel1 to bridge: %s", ast_channel_name(chana));
800 astman_send_error(s, m, buf);
801 ast_bridge_destroy(bridge, 0);
802 return 0;
803 }
804
805 ast_bridge_set_after_goto(chanb, chanb_context, chanb_exten, chanb_priority);
806 if (ast_bridge_add_channel(bridge, chanb, NULL, playtone & PLAYTONE_CHANNEL2, xfer_cfg_b ? xfer_cfg_b->xfersound : NULL)) {
807 snprintf(buf, sizeof(buf), "Unable to add Channel2 to bridge: %s", ast_channel_name(chanb));
808 astman_send_error(s, m, buf);
809 ast_bridge_destroy(bridge, 0);
810 return 0;
811 }
812
813 astman_send_ack(s, m, "Channels have been bridged");
814 ao2_cleanup(bridge);
815
816 return 0;
817}
818
819static char *app_bridge = "Bridge";
820
821enum {
831 OPT_CALLEE_PARK = (1 << 9),
832 OPT_CALLER_PARK = (1 << 10),
833 OPT_CALLEE_KILL = (1 << 11),
834 OPT_CALLEE_GO_ON = (1 << 12),
835 OPT_NOANSWER = (1 << 13),
836};
837
838enum {
842 /* note: this entry _MUST_ be the last one in the enum */
844};
845
862
864 char *parse, struct timeval *calldurationlimit)
865{
866 char *stringp = ast_strdupa(parse);
867 char *limit_str, *warning_str, *warnfreq_str;
868 const char *var;
869 int play_to_caller = 0, play_to_callee = 0;
870 int delta;
871
872 limit_str = strsep(&stringp, ":");
873 warning_str = strsep(&stringp, ":");
874 warnfreq_str = strsep(&stringp, ":");
875
876 config->timelimit = atol(limit_str);
877 if (warning_str)
878 config->play_warning = atol(warning_str);
879 if (warnfreq_str)
880 config->warning_freq = atol(warnfreq_str);
881
882 if (!config->timelimit) {
883 ast_log(LOG_WARNING, "Bridge does not accept L(%s)\n", limit_str);
884 config->timelimit = config->play_warning = config->warning_freq = 0;
885 config->warning_sound = NULL;
886 return -1; /* error */
887 } else if ( (delta = config->play_warning - config->timelimit) > 0) {
888 int w = config->warning_freq;
889
890 /*
891 * If the first warning is requested _after_ the entire call
892 * would end, and no warning frequency is requested, then turn
893 * off the warning. If a warning frequency is requested, reduce
894 * the 'first warning' time by that frequency until it falls
895 * within the call's total time limit.
896 *
897 * Graphically:
898 * timelim->| delta |<-playwarning
899 * 0__________________|_________________|
900 * | w | | | |
901 *
902 * so the number of intervals to cut is 1+(delta-1)/w
903 */
904 if (w == 0) {
905 config->play_warning = 0;
906 } else {
907 config->play_warning -= w * ( 1 + (delta-1)/w );
908 if (config->play_warning < 1)
909 config->play_warning = config->warning_freq = 0;
910 }
911 }
912
913 ast_channel_lock(chan);
914
915 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
916 play_to_caller = var ? ast_true(var) : 1;
917
918 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
919 play_to_callee = var ? ast_true(var) : 0;
920
921 if (!play_to_caller && !play_to_callee)
922 play_to_caller = 1;
923
924 var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
925 config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
926
927 /* The code looking at config wants a NULL, not just "", to decide
928 * that the message should not be played, so we replace "" with NULL.
929 * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
930 * not found.
931 */
932
933 var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
934 config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
935
936 var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
937 config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
938
939 ast_channel_unlock(chan);
940
941 /* undo effect of S(x) in case they are both used */
942 calldurationlimit->tv_sec = 0;
943 calldurationlimit->tv_usec = 0;
944
945 /* more efficient to do it like S(x) does since no advanced opts */
946 if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
947 calldurationlimit->tv_sec = config->timelimit / 1000;
948 calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
949 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
950 calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
951 play_to_caller = 0;
952 play_to_callee = 0;
953 config->timelimit = 0;
954 config->play_warning = 0;
955 config->warning_freq = 0;
956 } else {
957 ast_verb(4, "Limit Data for this call:\n");
958 ast_verb(4, "timelimit = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
959 ast_verb(4, "play_warning = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
960 ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
961 ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
962 ast_verb(4, "warning_freq = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
963 ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, ""));
964 ast_verb(4, "warning_sound = %s\n", config->warning_sound);
965 ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, ""));
966 }
967 if (play_to_caller)
968 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
969 if (play_to_callee)
970 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
971 return 0;
972}
973
974
975/*!
976 * \brief Bridge channels
977 * \param chan
978 * \param data channel to bridge with.
979 *
980 * Split data, check we aren't bridging with ourself, check valid channel,
981 * answer call if not already, check compatible channels, setup bridge config
982 * now bridge call, if transferred party hangs up return to PBX extension.
983 */
984static int bridge_exec(struct ast_channel *chan, const char *data)
985{
986 struct ast_channel *current_dest_chan = NULL;
987 char *tmp_data = NULL;
988 struct ast_flags opts = { 0, };
989 struct ast_bridge_config bconfig = { { 0, }, };
990 char *opt_args[OPT_ARG_ARRAY_SIZE];
991 struct timeval calldurationlimit = { 0, };
992 const char *context;
993 const char *extension;
994 int priority;
995 int bridge_add_failed;
996 int res = -1;
997 struct ast_bridge_features chan_features;
998 struct ast_bridge_features *peer_features;
999 struct ast_bridge *bridge;
1000 struct ast_features_xfer_config *xfer_cfg;
1001 int noanswer;
1002
1004 AST_APP_ARG(dest_chan);
1006 );
1007
1008 tmp_data = ast_strdupa(data ?: "");
1009 AST_STANDARD_APP_ARGS(args, tmp_data);
1010 if (!ast_strlen_zero(args.options)) {
1011 ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
1012 }
1013
1014 /* make sure we have a valid end point */
1015 if (!ast_strlen_zero(args.dest_chan)) {
1016 current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
1017 strlen(args.dest_chan));
1018 }
1019 if (!current_dest_chan) {
1020 ast_verb(4, "Bridge failed because channel '%s' does not exist\n",
1021 args.dest_chan ?: "");
1022 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
1023 return 0;
1024 }
1025
1026 /* avoid bridge with ourselves */
1027 if (chan == current_dest_chan) {
1028 ast_channel_unref(current_dest_chan);
1029 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", ast_channel_name(chan));
1030 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
1031 return 0;
1032 }
1033
1036 && ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
1037 goto done;
1038 }
1039
1044 if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
1046 if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
1052 if (ast_test_flag(&opts, OPT_CALLEE_PARK))
1054 if (ast_test_flag(&opts, OPT_CALLER_PARK))
1057
1058 /* Setup after bridge goto location. */
1059 if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
1060 ast_channel_lock(chan);
1064 ast_channel_unlock(chan);
1066 opt_args[OPT_ARG_CALLEE_GO_ON]);
1067 } else if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
1068 ast_channel_lock(current_dest_chan);
1069 context = ast_strdupa(ast_channel_context(current_dest_chan));
1070 extension = ast_strdupa(ast_channel_exten(current_dest_chan));
1071 priority = ast_channel_priority(current_dest_chan);
1072 ast_channel_unlock(current_dest_chan);
1074 }
1075
1076 if (ast_bridge_features_init(&chan_features)) {
1077 ast_bridge_features_cleanup(&chan_features);
1078 goto done;
1079 }
1080
1081 peer_features = ast_bridge_features_new();
1082 if (!peer_features) {
1083 ast_bridge_features_cleanup(&chan_features);
1084 goto done;
1085 }
1086
1087 if (pre_bridge_setup(chan, current_dest_chan, &bconfig, &chan_features, peer_features, noanswer)) {
1088 ast_bridge_features_destroy(peer_features);
1089 ast_bridge_features_cleanup(&chan_features);
1090 goto done;
1091 }
1092
1093 bridge = ast_bridge_basic_new();
1094 if (!bridge) {
1095 ast_bridge_features_destroy(peer_features);
1096 ast_bridge_features_cleanup(&chan_features);
1097 goto done;
1098 }
1099
1100 ast_channel_lock(current_dest_chan);
1101 xfer_cfg = ast_get_chan_features_xfer_config(current_dest_chan);
1102 ast_channel_unlock(current_dest_chan);
1103 bridge_add_failed = ast_bridge_add_channel(bridge, current_dest_chan, peer_features,
1105 xfer_cfg ? xfer_cfg->xfersound : NULL);
1106 ao2_cleanup(xfer_cfg);
1107 if (bridge_add_failed) {
1108 ast_bridge_features_cleanup(&chan_features);
1109 ast_bridge_destroy(bridge, 0);
1110 goto done;
1111 }
1112
1113 /* Don't keep the channel ref in case it was not already in a bridge. */
1114 current_dest_chan = ast_channel_unref(current_dest_chan);
1115
1116 res = ast_bridge_join(bridge, chan, NULL, &chan_features, NULL,
1118
1119 ast_bridge_features_cleanup(&chan_features);
1120
1121done:
1122 if (res == -1) {
1123 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
1124 } else {
1125 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
1126 }
1127
1128 ast_free((char *) bconfig.warning_sound);
1129 ast_free((char *) bconfig.end_sound);
1130 ast_free((char *) bconfig.start_sound);
1131
1132 ast_channel_cleanup(current_dest_chan);
1133 return 0;
1134}
1135
1136static int unload_module(void)
1137{
1139
1140 ast_manager_unregister("Bridge");
1141
1143
1144 return 0;
1145}
1146
1147static int load_module(void)
1148{
1149 int res;
1150
1151 res = load_features_config();
1154
1156}
1157
1159 .support_level = AST_MODULE_SUPPORT_CORE,
1160 .load = load_module,
1161 .unload = unload_module,
1163 .load_pri = AST_MODPRI_CORE,
1164 .requires = "extconfig",
Prototypes for public functions only of internal interest,.
@ noanswer
static int playtone(struct ast_channel *chan, int tone, int len)
#define var
Definition: ast_expr2f.c:605
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
Audiohooks Architecture.
Bridging API.
int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, enum ast_bridge_join_flags flags)
Join a channel to a bridge (blocking)
Definition: bridge.c:1690
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:1009
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:1947
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition: bridge.h:596
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:594
@ AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP
Definition: bridge.h:541
@ AST_BRIDGE_JOIN_PASS_REFERENCE
Definition: bridge.h:539
After Bridge Execution API.
int ast_bridge_setup_after_goto(struct ast_channel *chan)
Setup any after bridge goto location to begin execution.
Definition: bridge_after.c:435
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
Set channel to go on in the dialplan after the bridge.
Definition: bridge_after.c:622
void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set channel to goto specific location after the bridge.
Definition: bridge_after.c:612
Basic bridge subclass API.
void ast_bridge_basic_set_flags(struct ast_bridge *bridge, unsigned int flags)
Set feature flags on a basic bridge.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
int ast_bridge_features_ds_append(struct ast_channel *chan, struct ast_flags *flags)
Append basic bridge DTMF feature flags on the channel.
Definition: bridge_basic.c:263
Channel Bridging API.
int ast_bridge_features_set_limits(struct ast_bridge_features *features, struct ast_bridge_features_limits *limits, enum ast_bridge_hook_remove_flags remove_flags)
Limit the amount of time a channel may stay in the bridge and optionally play warning messages as tim...
Definition: bridge.c:3481
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3689
int ast_bridge_features_limits_construct(struct ast_bridge_features_limits *limits)
Constructor function for ast_bridge_features_limits.
Definition: bridge.c:3465
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3752
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3722
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3743
void ast_bridge_features_limits_destroy(struct ast_bridge_features_limits *limits)
Destructor function for ast_bridge_features_limits.
Definition: bridge.c:3476
Internal Asterisk hangup causes.
static int priority
static const char config[]
Definition: chan_ooh323.c:111
General Asterisk PBX channel definitions.
const char * ast_channel_linkedid(const struct ast_channel *chan)
const char * ast_channel_name(const struct ast_channel *chan)
@ AST_FEATURE_AUTOMIXMON
Definition: channel.h:1089
@ AST_FEATURE_REDIRECT
Definition: channel.h:1084
@ AST_FEATURE_PARKCALL
Definition: channel.h:1088
@ AST_FEATURE_AUTOMON
Definition: channel.h:1087
@ AST_FEATURE_DISCONNECT
Definition: channel.h:1085
@ AST_FEATURE_PLAY_WARNING
Definition: channel.h:1083
struct ast_channel * ast_channel_masq(const struct ast_channel *chan)
const char * ast_channel_data(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2414
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
Definition: channel.h:2418
int ast_raw_answer_with_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Answer a channel passing in a stream topology.
Definition: channel.c:2668
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:194
#define ast_channel_lock(chan)
Definition: channel.h:2970
struct ast_cdr * ast_channel_cdr(const struct ast_channel *chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_accountcode(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1461
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
Definition: channel.h:2420
const char * ast_channel_appl(const struct ast_channel *chan)
enum ama_flags ast_channel_amaflags(const struct ast_channel *chan)
const char * ast_channel_dialcontext(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3006
@ AST_FLAG_IN_AUTOLOOP
Definition: channel.h:1017
#define AST_FEATURE_DTMF_MASK
Definition: channel.h:1092
struct ast_channel * ast_channel_masqr(const struct ast_channel *chan)
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
int ast_channel_visible_indication(const struct ast_channel *chan)
void ast_autoservice_chan_hangup_peer(struct ast_channel *chan, struct ast_channel *peer)
Put chan into autoservice while hanging up peer.
Definition: autoservice.c:349
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3017
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4294
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2971
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2428
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1146
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_UP
Definition: channelstate.h:42
Standard Command Line Interface.
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Device state management.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static void bridge_config_set_limits_warning_values(struct ast_bridge_config *config, struct ast_bridge_features_limits *limits)
Definition: features.c:448
@ OPT_CALLEE_PARK
Definition: features.c:831
@ OPT_DURATION_LIMIT
Definition: features.c:825
@ OPT_DURATION_STOP
Definition: features.c:826
@ OPT_NOANSWER
Definition: features.c:835
@ OPT_CALLEE_TRANSFER
Definition: features.c:827
@ OPT_CALLEE_GO_ON
Definition: features.c:834
@ OPT_CALLER_PARK
Definition: features.c:832
@ OPT_CALLER_MONITOR
Definition: features.c:830
@ OPT_CALLEE_MONITOR
Definition: features.c:829
@ OPT_CALLER_HANGUP
Definition: features.c:824
@ OPT_CALLEE_HANGUP
Definition: features.c:823
@ BRIDGE_OPT_PLAYTONE
Definition: features.c:822
@ OPT_CALLEE_KILL
Definition: features.c:833
@ OPT_CALLER_TRANSFER
Definition: features.c:828
static const struct ast_app_option bridge_exec_options[128]
Definition: features.c:861
void ast_channel_log(char *title, struct ast_channel *chan)
Definition: features.c:375
static char * app_bridge
Definition: features.c:819
static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, struct ast_bridge_features *chan_features, struct ast_bridge_features *peer_features, int noanswer)
Definition: features.c:503
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
Definition: features.c:434
int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
bridge the call and set CDR
Definition: features.c:691
static void bridge_config_set_limits(struct ast_bridge_config *config, struct ast_bridge_features_limits *caller_limits, struct ast_bridge_features_limits *callee_limits)
Definition: features.c:473
static int action_bridge(struct mansession *s, const struct message *m)
Bridge channels together.
Definition: features.c:732
@ OPT_ARG_CALLEE_GO_ON
Definition: features.c:841
@ OPT_ARG_DURATION_STOP
Definition: features.c:840
@ OPT_ARG_DURATION_LIMIT
Definition: features.c:839
@ OPT_ARG_ARRAY_SIZE
Definition: features.c:843
static int bridge_exec(struct ast_channel *chan, const char *data)
Bridge channels.
Definition: features.c:984
int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags)
Bridge a call, and add additional flags to the bridge.
Definition: features.c:601
play_tone_action
Definition: features.c:696
@ PLAYTONE_CHANNEL1
Definition: features.c:698
@ PLAYTONE_CHANNEL2
Definition: features.c:699
@ PLAYTONE_NONE
Definition: features.c:697
@ PLAYTONE_BOTH
Definition: features.c:700
int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *config, char *parse, struct timeval *calldurationlimit)
parse L option and read associated channel variables to set warning, warning frequency,...
Definition: features.c:863
static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
Definition: features.c:346
static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel *peer)
Definition: features.c:495
static int load_module(void)
Definition: features.c:1147
static enum play_tone_action parse_playtone(const char *playtone_val)
Definition: features.c:703
static void * dial_features_duplicate(void *data)
Definition: features.c:274
static int unload_module(void)
Definition: features.c:1136
static const struct ast_datastore_info dial_features_info
Definition: features.c:287
feature_interpret_op
Definition: features.c:261
@ FEATURE_INTERPRET_CHECK
Definition: features.c:264
@ FEATURE_INTERPRET_DO
Definition: features.c:263
@ FEATURE_INTERPRET_DETECT
Definition: features.c:262
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
Definition: features.c:394
static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
Definition: features.c:303
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_bridge_features *features, int play_tone, const char *xfersound)
Add an arbitrary channel to a bridge.
Definition: bridge.c:2540
void unload_features_config(void)
int load_features_config(void)
int reload_features_config(void)
Generic File Format Support. Should be included by clients of the file handling routines....
globally accessible channel datastores
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
#define SCOPE_TRACE(__level,...)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define END_OPTIONS
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define BEGIN_OPTIONS
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
Configuration File Parser.
struct ast_features_xfer_config * ast_get_chan_features_xfer_config(struct ast_channel *chan)
Get the transfer configuration options for a channel.
struct ao2_container * ast_get_chan_applicationmap(struct ast_channel *chan)
Get the applicationmap for a given channel.
@ AST_CONTROL_RINGING
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
Asterisk locking-related definitions:
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:203
#define EVENT_FLAG_CALL
Definition: manager.h:76
int ast_max_forwards_reset(struct ast_channel *chan)
Reset the max forwards on a channel to its starting value.
Definition: max_forwards.c:151
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:330
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx_app.c:104
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CORE
Definition: module.h:338
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
Music on hold handling.
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.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4723
static int reload(void)
#define NULL
Definition: resample.c:96
Say numbers and dates (maybe words one day too)
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
Media Stream API.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
Generic container type.
bridge configuration
Definition: channel.h:1096
const char * end_sound
Definition: channel.h:1107
const char * warning_sound
Definition: channel.h:1106
struct ast_flags features_callee
Definition: channel.h:1098
struct ast_flags features_caller
Definition: channel.h:1097
const char * start_sound
Definition: channel.h:1108
Structure that contains configuration information for the limits feature.
Structure that contains features information.
struct ast_channel * peer
Definition: features.c:342
struct ast_bridge_config bconfig
Definition: features.c:340
struct ast_channel * chan
Definition: features.c:341
unsigned int return_to_pbx
Definition: features.c:343
Structure that contains information about a bridge.
Definition: bridge.h:353
Main Channel structure associated with a channel.
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
unsigned int inheritance
Definition: datastore.h:69
struct ast_flags peer_features
Definition: features.c:271
struct ast_flags my_features
Definition: features.c:269
Feature configuration relating to transfers.
Structure used to handle boolean flags.
Definition: utils.h:199
structure to hold extensions
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:327
int value
Definition: syslog.c:37
Test Framework API.
int done
Definition: test_amihooks.c:48
const char * args
static struct test_options options
Support for translation of data formats. translate.c.
Utility functions.
#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
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define AST_FLAGS_ALL
Definition: utils.h:196