Asterisk - The Open Source Telephony Project GIT-master-a358458
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 <synopsis>
84 Bridge two channels.
85 </synopsis>
86 <syntax>
87 <parameter name="channel" required="true">
88 <para>The current channel is bridged to the channel
89 identified by the channel name, channel name prefix, or channel
90 uniqueid.</para>
91 </parameter>
92 <parameter name="options">
93 <optionlist>
94 <option name="p">
95 <para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
96 </option>
97 <option name="F" argsep="^">
98 <argument name="context" required="false" />
99 <argument name="exten" required="false" />
100 <argument name="priority" required="true" />
101 <para>When the bridger hangs up, transfer the <emphasis>bridged</emphasis> party
102 to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
103 <note>
104 <para>Any channel variables you want the called channel to inherit from the caller channel must be
105 prefixed with one or two underbars ('_').</para>
106 </note>
107 <note>
108 <para>This option will override the 'x' option</para>
109 </note>
110 </option>
111 <option name="F">
112 <para>When the bridger hangs up, transfer the <emphasis>bridged</emphasis> party
113 to the next priority of the current extension and <emphasis>start</emphasis> execution
114 at that location.</para>
115 <note>
116 <para>Any channel variables you want the called channel to inherit from the caller channel must be
117 prefixed with one or two underbars ('_').</para>
118 </note>
119 <note>
120 <para>Using this option from a or GoSub() might not make sense as there would be no return points.</para>
121 </note>
122 <note>
123 <para>This option will override the 'x' option</para>
124 </note>
125 </option>
126
127 <option name="h">
128 <para>Allow the called party to hang up by sending the
129 <replaceable>*</replaceable> DTMF digit.</para>
130 </option>
131 <option name="H">
132 <para>Allow the calling party to hang up by pressing the
133 <replaceable>*</replaceable> DTMF digit.</para>
134 </option>
135 <option name="k">
136 <para>Allow the called party to enable parking of the call by sending
137 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
138 </option>
139 <option name="K">
140 <para>Allow the calling party to enable parking of the call by sending
141 the DTMF sequence defined for call parking in <filename>features.conf</filename>.</para>
142 </option>
143 <option name="L(x[:y][:z])">
144 <para>Limit the call to <replaceable>x</replaceable> ms. Play a warning
145 when <replaceable>y</replaceable> ms are left. Repeat the warning every
146 <replaceable>z</replaceable> ms. The following special variables can be
147 used with this option:</para>
148 <variablelist>
149 <variable name="LIMIT_PLAYAUDIO_CALLER">
150 <para>Play sounds to the caller. yes|no (default yes)</para>
151 </variable>
152 <variable name="LIMIT_PLAYAUDIO_CALLEE">
153 <para>Play sounds to the callee. yes|no</para>
154 </variable>
155 <variable name="LIMIT_TIMEOUT_FILE">
156 <para>File to play when time is up.</para>
157 </variable>
158 <variable name="LIMIT_CONNECT_FILE">
159 <para>File to play when call begins.</para>
160 </variable>
161 <variable name="LIMIT_WARNING_FILE">
162 <para>File to play as warning if <replaceable>y</replaceable> is
163 defined. The default is to say the time remaining.</para>
164 </variable>
165 </variablelist>
166 </option>
167 <option name="n">
168 <para>Do not answer the channel automatically before bridging.</para>
169 <para>Additionally, to prevent a bridged channel (the target of the Bridge application)
170 from answering, the <literal>BRIDGE_NOANSWER</literal> variable can be set to inhibit
171 answering.</para>
172 </option>
173 <option name="S(x)">
174 <para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
175 </option>
176 <option name="t">
177 <para>Allow the called party to transfer the calling party by sending the
178 DTMF sequence defined in <filename>features.conf</filename>.</para>
179 </option>
180 <option name="T">
181 <para>Allow the calling party to transfer the called party by sending the
182 DTMF sequence defined in <filename>features.conf</filename>.</para>
183 </option>
184 <option name="w">
185 <para>Allow the called party to enable recording of the call by sending
186 the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
187 </option>
188 <option name="W">
189 <para>Allow the calling party to enable recording of the call by sending
190 the DTMF sequence defined for one-touch recording in <filename>features.conf</filename>.</para>
191 </option>
192 <option name="x">
193 <para>Cause the called party to be hung up after the bridge, instead of being
194 restarted in the dialplan.</para>
195 </option>
196 </optionlist>
197 </parameter>
198 </syntax>
199 <description>
200 <para>Allows the ability to bridge two channels via the dialplan.</para>
201 <para>This application sets the following channel variable upon completion:</para>
202 <variablelist>
203 <variable name="BRIDGERESULT">
204 <para>The result of the bridge attempt as a text string.</para>
205 <value name="SUCCESS" />
206 <value name="FAILURE" />
207 <value name="LOOP" />
208 <value name="NONEXISTENT" />
209 </variable>
210 </variablelist>
211 </description>
212 <see-also>
213 <ref type="manager">Bridge</ref>
214 <ref type="managerEvent">BridgeCreate</ref>
215 <ref type="managerEvent">BridgeEnter</ref>
216 </see-also>
217 </application>
218 <manager name="Bridge" language="en_US">
219 <synopsis>
220 Bridge two channels already in the PBX.
221 </synopsis>
222 <syntax>
223 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
224 <parameter name="Channel1" required="true">
225 <para>Channel to Bridge to Channel2.</para>
226 </parameter>
227 <parameter name="Channel2" required="true">
228 <para>Channel to Bridge to Channel1.</para>
229 </parameter>
230 <parameter name="Tone">
231 <para>Play courtesy tone to Channel 2.</para>
232 <enumlist>
233 <enum name="no" />
234 <enum name="Channel1" />
235 <enum name="Channel2" />
236 <enum name="Both" />
237 </enumlist>
238 </parameter>
239 </syntax>
240 <description>
241 <para>Bridge together two channels already in the PBX.</para>
242 </description>
243 <see-also>
244 <ref type="application">Bridge</ref>
245 <ref type="managerEvent">BridgeCreate</ref>
246 <ref type="managerEvent">BridgeEnter</ref>
247 <ref type="manager">BridgeDestroy</ref>
248 <ref type="manager">BridgeInfo</ref>
249 <ref type="manager">BridgeKick</ref>
250 <ref type="manager">BridgeList</ref>
251 </see-also>
252 </manager>
253 ***/
254
255typedef enum {
256 FEATURE_INTERPRET_DETECT, /* Used by ast_feature_detect */
257 FEATURE_INTERPRET_DO, /* Used by feature_interpret */
258 FEATURE_INTERPRET_CHECK, /* Used by feature_check */
260
262 /*! Channel's feature flags. */
264 /*! Bridge peer's feature flags. */
266};
267
268static void *dial_features_duplicate(void *data)
269{
270 struct ast_dial_features *df = data, *df_copy;
271
272 if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
273 return NULL;
274 }
275
276 memcpy(df_copy, df, sizeof(*df));
277
278 return df_copy;
279}
280
282 .type = "dial-features",
283 .destroy = ast_free_ptr,
284 .duplicate = dial_features_duplicate,
285};
286
287/*!
288 * \internal
289 * \brief Set the features datastore if it doesn't exist.
290 *
291 * \param chan Channel to add features datastore
292 * \param my_features The channel's feature flags
293 * \param peer_features The channel's bridge peer feature flags
294 *
295 * \retval TRUE if features datastore already existed.
296 */
297static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
298{
299 struct ast_datastore *datastore;
300 struct ast_dial_features *dialfeatures;
301
302 ast_channel_lock(chan);
304 ast_channel_unlock(chan);
305 if (datastore) {
306 /* Already exists. */
307 return 1;
308 }
309
310 /* Create a new datastore with specified feature flags. */
312 if (!datastore) {
313 ast_log(LOG_WARNING, "Unable to create channel features datastore.\n");
314 return 0;
315 }
316 dialfeatures = ast_calloc(1, sizeof(*dialfeatures));
317 if (!dialfeatures) {
318 ast_log(LOG_WARNING, "Unable to allocate memory for feature flags.\n");
319 ast_datastore_free(datastore);
320 return 0;
321 }
325 datastore->data = dialfeatures;
326 ast_channel_lock(chan);
327 ast_channel_datastore_add(chan, datastore);
328 ast_channel_unlock(chan);
329 return 0;
330}
331
333{
337 unsigned int return_to_pbx:1;
338};
339
340static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
341{
343
344 if (ast_test_flag(&config->features_caller, AST_FEATURE_DTMF_MASK)) {
346 }
347 if (ast_test_flag(&config->features_callee, AST_FEATURE_DTMF_MASK)) {
349 }
350
352 RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
353
354 ast_channel_lock(chan);
355 applicationmap = ast_get_chan_applicationmap(chan);
356 ast_channel_unlock(chan);
357
358 if (!applicationmap) {
359 return;
360 }
361
362 /* If an applicationmap exists for this channel at all, then the channel needs the DTMF flag set */
364 }
365}
366
367void ast_channel_log(char *title, struct ast_channel *chan);
368
369void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */
370{
371 ast_log(LOG_NOTICE, "______ %s (%lx)______\n", title, (unsigned long) chan);
372 ast_log(LOG_NOTICE, "CHAN: name: %s; appl: %s; data: %s; contxt: %s; exten: %s; pri: %d;\n",
375 ast_log(LOG_NOTICE, "CHAN: acctcode: %s; dialcontext: %s; amaflags: %x;\n",
377 ast_log(LOG_NOTICE, "CHAN: masq: %p; masqr: %p; uniqueID: %s; linkedID:%s\n",
380 if (ast_channel_masqr(chan)) {
381 ast_log(LOG_NOTICE, "CHAN: masquerading as: %s; cdr: %p;\n",
383 }
384
385 ast_log(LOG_NOTICE, "===== done ====\n");
386}
387
388static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
389{
390 const char *feature;
391
392 if (ast_strlen_zero(features)) {
393 return;
394 }
395
396 for (feature = features; *feature; feature++) {
397 struct ast_flags *party;
398
399 if (isupper(*feature)) {
400 party = &config->features_caller;
401 } else {
402 party = &config->features_callee;
403 }
404
405 switch (tolower(*feature)) {
406 case 't' :
408 break;
409 case 'k' :
411 break;
412 case 'h' :
414 break;
415 case 'w' :
417 break;
418 case 'x' :
420 break;
421 default :
422 ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
423 break;
424 }
425 }
426}
427
428static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
429{
430 if (add_features_datastore(caller, &config->features_caller, &config->features_callee)) {
431 /*
432 * If we don't return here, then when we do a builtin_atxfer we
433 * will copy the disconnect flags over from the atxfer to the
434 * callee (Party C).
435 */
436 return;
437 }
438
439 add_features_datastore(callee, &config->features_callee, &config->features_caller);
440}
441
443{
444 if (config->end_sound) {
445 ast_string_field_set(limits, duration_sound, config->end_sound);
446 }
447
448 if (config->warning_sound) {
449 ast_string_field_set(limits, warning_sound, config->warning_sound);
450 }
451
452 if (config->start_sound) {
453 ast_string_field_set(limits, connect_sound, config->start_sound);
454 }
455
456 limits->frequency = config->warning_freq;
457 limits->warning = config->play_warning;
458}
459
460/*!
461 * \internal brief Setup limit hook structures on calls that need limits
462 *
463 * \param config ast_bridge_config which provides the limit data
464 * \param caller_limits pointer to an ast_bridge_features_limits struct which will store the caller side limits
465 * \param callee_limits pointer to an ast_bridge_features_limits struct which will store the callee side limits
466 */
467static void bridge_config_set_limits(struct ast_bridge_config *config, struct ast_bridge_features_limits *caller_limits, struct ast_bridge_features_limits *callee_limits)
468{
469 if (ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING)) {
471 }
472
473 if (ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING)) {
475 }
476
477 caller_limits->duration = config->timelimit;
478 callee_limits->duration = config->timelimit;
479}
480
481/*!
482 * \internal
483 * \brief Send the peer channel on its way on bridge start failure.
484 * \since 12.0.0
485 *
486 * \param chan Chan to put into autoservice.
487 * \param peer Chan to send to after bridge goto or run hangup handlers and hangup.
488 */
489static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel *peer)
490{
492 || ast_pbx_start(peer)) {
494 }
495}
496
497static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config,
498 struct ast_bridge_features *chan_features, struct ast_bridge_features *peer_features, int noanswer)
499{
500 int res;
501 SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
502
504 add_features_datastores(chan, peer, config);
505
506 /*
507 * This is an interesting case. One example is if a ringing
508 * channel gets redirected to an extension that picks up a
509 * parked call. This will make sure that the call taken out of
510 * parking gets told that the channel it just got bridged to is
511 * still ringing.
512 */
516 }
517
519
520 /* Answer if need be */
521
522 res = 0;
523
524 if (noanswer) {
525 ast_debug(1, "Skipping answer on %s due to no answer directive\n", ast_channel_name(chan));
526 } else if (ast_channel_state(chan) != AST_STATE_UP) {
527 ast_debug(1, "Answering channel for bridge: %s\n", ast_channel_name(chan));
528 res = ast_raw_answer_with_stream_topology(chan, config->answer_topology);
529 if (res != 0) {
530 return -1;
531 }
532 }
533
534
535#ifdef FOR_DEBUG
536 /* show the two channels and cdrs involved in the bridge for debug & devel purposes */
537 ast_channel_log("Pre-bridge CHAN Channel info", chan);
538 ast_channel_log("Pre-bridge PEER Channel info", peer);
539#endif
540
541 res = 0;
542 ast_channel_lock(chan);
544 res |= ast_bridge_features_ds_append(chan, &config->features_caller);
545 ast_channel_unlock(chan);
546 ast_channel_lock(peer);
548 res |= ast_bridge_features_ds_append(peer, &config->features_callee);
549 ast_channel_unlock(peer);
550
551 if (res) {
552 return -1;
553 }
554
555 if (config->timelimit) {
556 struct ast_bridge_features_limits call_duration_limits_chan;
557 struct ast_bridge_features_limits call_duration_limits_peer;
558 int abandon_call = 0; /* TRUE if set limits fails so we can abandon the call. */
559
560 if (ast_bridge_features_limits_construct(&call_duration_limits_chan)) {
561 ast_log(LOG_ERROR, "Could not construct caller duration limits. Bridge canceled.\n");
562
563 return -1;
564 }
565
566 if (ast_bridge_features_limits_construct(&call_duration_limits_peer)) {
567 ast_log(LOG_ERROR, "Could not construct callee duration limits. Bridge canceled.\n");
568 ast_bridge_features_limits_destroy(&call_duration_limits_chan);
569
570 return -1;
571 }
572
573 bridge_config_set_limits(config, &call_duration_limits_chan, &call_duration_limits_peer);
574
575 if (ast_bridge_features_set_limits(chan_features, &call_duration_limits_chan, 0)) {
576 abandon_call = 1;
577 }
578 if (ast_bridge_features_set_limits(peer_features, &call_duration_limits_peer, 0)) {
579 abandon_call = 1;
580 }
581
582 /* At this point we are done with the limits structs since they have been copied to the individual feature sets. */
583 ast_bridge_features_limits_destroy(&call_duration_limits_chan);
584 ast_bridge_features_limits_destroy(&call_duration_limits_peer);
585
586 if (abandon_call) {
587 ast_log(LOG_ERROR, "Could not set duration limits on one or more sides of the call. Bridge canceled.\n");
588 return -1;
589 }
590 }
591
592 return 0;
593}
594
595int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags)
596{
597 int res;
598 struct ast_bridge *bridge;
599 struct ast_bridge_features chan_features;
600 struct ast_bridge_features *peer_features;
601 const char *value;
602 int noanswer;
603 SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
604
605 /* Setup features. */
606 res = ast_bridge_features_init(&chan_features);
607 peer_features = ast_bridge_features_new();
608 if (res || !peer_features) {
609 ast_bridge_features_destroy(peer_features);
610 ast_bridge_features_cleanup(&chan_features);
611 bridge_failed_peer_goto(chan, peer);
612 return -1;
613 }
614
615 ast_channel_lock(chan);
616 value = pbx_builtin_getvar_helper(chan, "BRIDGE_NOANSWER");
617 noanswer = !ast_strlen_zero(value) ? 1 : 0;
618 ast_channel_unlock(chan);
619
620 if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features, noanswer)) {
621 ast_bridge_features_destroy(peer_features);
622 ast_bridge_features_cleanup(&chan_features);
623 bridge_failed_peer_goto(chan, peer);
624 return -1;
625 }
626
627 /* Create bridge */
628 bridge = ast_bridge_basic_new();
629 if (!bridge) {
630 ast_bridge_features_destroy(peer_features);
631 ast_bridge_features_cleanup(&chan_features);
632 bridge_failed_peer_goto(chan, peer);
633 return -1;
634 }
635
636 ast_bridge_basic_set_flags(bridge, flags);
637
638 /* Put peer into the bridge */
639 if (ast_bridge_impart(bridge, peer, NULL, peer_features,
641 ast_bridge_destroy(bridge, 0);
642 ast_bridge_features_cleanup(&chan_features);
643 bridge_failed_peer_goto(chan, peer);
644 return -1;
645 }
646
647 /* Join bridge */
648 ast_bridge_join(bridge, chan, NULL, &chan_features, NULL,
650
651 /*
652 * If the bridge was broken for a hangup that isn't real, then
653 * don't run the h extension, because the channel isn't really
654 * hung up. This should really only happen with
655 * AST_SOFTHANGUP_ASYNCGOTO.
656 */
657 res = -1;
658 ast_channel_lock(chan);
660 res = 0;
661 }
662 ast_channel_unlock(chan);
663
664 ast_bridge_features_cleanup(&chan_features);
665
666 if (res && config->end_bridge_callback) {
667 config->end_bridge_callback(config->end_bridge_callback_data);
668 }
669
670 return res;
671}
672
673/*!
674 * \brief bridge the call and set CDR
675 *
676 * \param chan The bridge considers this channel the caller.
677 * \param peer The bridge considers this channel the callee.
678 * \param config Configuration for this bridge.
679 *
680 * Set start time, check for two channels,check if monitor on
681 * check for feature activation, create new CDR
682 * \return res on success.
683 * \retval -1 on failure to bridge.
684 */
685int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
686{
687 return ast_bridge_call_with_flags(chan, peer, config, 0);
688}
689
695};
696
697static enum play_tone_action parse_playtone(const char *playtone_val)
698{
699 if (ast_strlen_zero(playtone_val) || ast_false(playtone_val)) {
700 return PLAYTONE_NONE;
701 } if (!strcasecmp(playtone_val, "channel1")) {
702 return PLAYTONE_CHANNEL1;
703 } else if (!strcasecmp(playtone_val, "channel2") || ast_true(playtone_val)) {
704 return PLAYTONE_CHANNEL2;
705 } else if (!strcasecmp(playtone_val, "both")) {
706 return PLAYTONE_BOTH;
707 } else {
708 /* Invalid input. Assume none */
709 return PLAYTONE_NONE;
710 }
711}
712
713/*!
714 * \brief Bridge channels together
715 * \param s
716 * \param m
717 *
718 * Make sure valid channels were specified,
719 * send errors if any of the channels could not be found/locked, answer channels if needed,
720 * create the placeholder channels and grab the other channels
721 * make the channels compatible, send error if we fail doing so
722 * setup the bridge thread object and start the bridge.
723 *
724 * \retval 0
725 */
726static int action_bridge(struct mansession *s, const struct message *m)
727{
728 const char *channela = astman_get_header(m, "Channel1");
729 const char *channelb = astman_get_header(m, "Channel2");
731 RAII_VAR(struct ast_channel *, chana, NULL, ao2_cleanup);
732 RAII_VAR(struct ast_channel *, chanb, NULL, ao2_cleanup);
733 const char *chana_exten;
734 const char *chana_context;
735 int chana_priority;
736 const char *chanb_exten;
737 const char *chanb_context;
738 int chanb_priority;
739 struct ast_bridge *bridge;
740 char buf[256];
741 RAII_VAR(struct ast_features_xfer_config *, xfer_cfg_a, NULL, ao2_cleanup);
742 RAII_VAR(struct ast_features_xfer_config *, xfer_cfg_b, NULL, ao2_cleanup);
743
744 /* make sure valid channels were specified */
745 if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
746 astman_send_error(s, m, "Missing channel parameter in request");
747 return 0;
748 }
749
750 ast_debug(1, "Performing Bridge action on %s and %s\n", channela, channelb);
751
752 /* Start with chana */
753 chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
754 if (!chana) {
755 snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela);
756 astman_send_error(s, m, buf);
757 return 0;
758 }
759 ast_channel_lock(chana);
760 xfer_cfg_a = ast_get_chan_features_xfer_config(chana);
761 chana_exten = ast_strdupa(ast_channel_exten(chana));
762 chana_context = ast_strdupa(ast_channel_context(chana));
763 chana_priority = ast_channel_priority(chana);
765 chana_priority++;
766 }
767 ast_channel_unlock(chana);
768
769 chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
770 if (!chanb) {
771 snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb);
772 astman_send_error(s, m, buf);
773 return 0;
774 }
775 ast_channel_lock(chanb);
776 xfer_cfg_b = ast_get_chan_features_xfer_config(chanb);
777 chanb_exten = ast_strdupa(ast_channel_exten(chanb));
778 chanb_context = ast_strdupa(ast_channel_context(chanb));
779 chanb_priority = ast_channel_priority(chanb);
781 chanb_priority++;
782 }
783 ast_channel_unlock(chanb);
784
785 bridge = ast_bridge_basic_new();
786 if (!bridge) {
787 astman_send_error(s, m, "Unable to create bridge\n");
788 return 0;
789 }
790
791 ast_bridge_set_after_goto(chana, chana_context, chana_exten, chana_priority);
792 if (ast_bridge_add_channel(bridge, chana, NULL, playtone & PLAYTONE_CHANNEL1, xfer_cfg_a ? xfer_cfg_a->xfersound : NULL)) {
793 snprintf(buf, sizeof(buf), "Unable to add Channel1 to bridge: %s", ast_channel_name(chana));
794 astman_send_error(s, m, buf);
795 ast_bridge_destroy(bridge, 0);
796 return 0;
797 }
798
799 ast_bridge_set_after_goto(chanb, chanb_context, chanb_exten, chanb_priority);
800 if (ast_bridge_add_channel(bridge, chanb, NULL, playtone & PLAYTONE_CHANNEL2, xfer_cfg_b ? xfer_cfg_b->xfersound : NULL)) {
801 snprintf(buf, sizeof(buf), "Unable to add Channel2 to bridge: %s", ast_channel_name(chanb));
802 astman_send_error(s, m, buf);
803 ast_bridge_destroy(bridge, 0);
804 return 0;
805 }
806
807 astman_send_ack(s, m, "Channels have been bridged");
808 ao2_cleanup(bridge);
809
810 return 0;
811}
812
813static char *app_bridge = "Bridge";
814
815enum {
825 OPT_CALLEE_PARK = (1 << 9),
826 OPT_CALLER_PARK = (1 << 10),
827 OPT_CALLEE_KILL = (1 << 11),
828 OPT_CALLEE_GO_ON = (1 << 12),
829 OPT_NOANSWER = (1 << 13),
830};
831
832enum {
836 /* note: this entry _MUST_ be the last one in the enum */
838};
839
856
858 char *parse, struct timeval *calldurationlimit)
859{
860 char *stringp = ast_strdupa(parse);
861 char *limit_str, *warning_str, *warnfreq_str;
862 const char *var;
863 int play_to_caller = 0, play_to_callee = 0;
864 int delta;
865
866 limit_str = strsep(&stringp, ":");
867 warning_str = strsep(&stringp, ":");
868 warnfreq_str = strsep(&stringp, ":");
869
870 config->timelimit = atol(limit_str);
871 if (warning_str)
872 config->play_warning = atol(warning_str);
873 if (warnfreq_str)
874 config->warning_freq = atol(warnfreq_str);
875
876 if (!config->timelimit) {
877 ast_log(LOG_WARNING, "Bridge does not accept L(%s)\n", limit_str);
878 config->timelimit = config->play_warning = config->warning_freq = 0;
879 config->warning_sound = NULL;
880 return -1; /* error */
881 } else if ( (delta = config->play_warning - config->timelimit) > 0) {
882 int w = config->warning_freq;
883
884 /*
885 * If the first warning is requested _after_ the entire call
886 * would end, and no warning frequency is requested, then turn
887 * off the warning. If a warning frequency is requested, reduce
888 * the 'first warning' time by that frequency until it falls
889 * within the call's total time limit.
890 *
891 * Graphically:
892 * timelim->| delta |<-playwarning
893 * 0__________________|_________________|
894 * | w | | | |
895 *
896 * so the number of intervals to cut is 1+(delta-1)/w
897 */
898 if (w == 0) {
899 config->play_warning = 0;
900 } else {
901 config->play_warning -= w * ( 1 + (delta-1)/w );
902 if (config->play_warning < 1)
903 config->play_warning = config->warning_freq = 0;
904 }
905 }
906
907 ast_channel_lock(chan);
908
909 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLER");
910 play_to_caller = var ? ast_true(var) : 1;
911
912 var = pbx_builtin_getvar_helper(chan, "LIMIT_PLAYAUDIO_CALLEE");
913 play_to_callee = var ? ast_true(var) : 0;
914
915 if (!play_to_caller && !play_to_callee)
916 play_to_caller = 1;
917
918 var = pbx_builtin_getvar_helper(chan, "LIMIT_WARNING_FILE");
919 config->warning_sound = !ast_strlen_zero(var) ? ast_strdup(var) : ast_strdup("timeleft");
920
921 /* The code looking at config wants a NULL, not just "", to decide
922 * that the message should not be played, so we replace "" with NULL.
923 * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
924 * not found.
925 */
926
927 var = pbx_builtin_getvar_helper(chan, "LIMIT_TIMEOUT_FILE");
928 config->end_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
929
930 var = pbx_builtin_getvar_helper(chan, "LIMIT_CONNECT_FILE");
931 config->start_sound = !ast_strlen_zero(var) ? ast_strdup(var) : NULL;
932
933 ast_channel_unlock(chan);
934
935 /* undo effect of S(x) in case they are both used */
936 calldurationlimit->tv_sec = 0;
937 calldurationlimit->tv_usec = 0;
938
939 /* more efficient to do it like S(x) does since no advanced opts */
940 if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
941 calldurationlimit->tv_sec = config->timelimit / 1000;
942 calldurationlimit->tv_usec = (config->timelimit % 1000) * 1000;
943 ast_verb(3, "Setting call duration limit to %.3lf seconds.\n",
944 calldurationlimit->tv_sec + calldurationlimit->tv_usec / 1000000.0);
945 play_to_caller = 0;
946 play_to_callee = 0;
947 config->timelimit = 0;
948 config->play_warning = 0;
949 config->warning_freq = 0;
950 } else {
951 ast_verb(4, "Limit Data for this call:\n");
952 ast_verb(4, "timelimit = %ld ms (%.3lf s)\n", config->timelimit, config->timelimit / 1000.0);
953 ast_verb(4, "play_warning = %ld ms (%.3lf s)\n", config->play_warning, config->play_warning / 1000.0);
954 ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
955 ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
956 ast_verb(4, "warning_freq = %ld ms (%.3lf s)\n", config->warning_freq, config->warning_freq / 1000.0);
957 ast_verb(4, "start_sound = %s\n", S_OR(config->start_sound, ""));
958 ast_verb(4, "warning_sound = %s\n", config->warning_sound);
959 ast_verb(4, "end_sound = %s\n", S_OR(config->end_sound, ""));
960 }
961 if (play_to_caller)
962 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
963 if (play_to_callee)
964 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
965 return 0;
966}
967
968
969/*!
970 * \brief Bridge channels
971 * \param chan
972 * \param data channel to bridge with.
973 *
974 * Split data, check we aren't bridging with ourself, check valid channel,
975 * answer call if not already, check compatible channels, setup bridge config
976 * now bridge call, if transferred party hangs up return to PBX extension.
977 */
978static int bridge_exec(struct ast_channel *chan, const char *data)
979{
980 struct ast_channel *current_dest_chan = NULL;
981 char *tmp_data = NULL;
982 struct ast_flags opts = { 0, };
983 struct ast_bridge_config bconfig = { { 0, }, };
984 char *opt_args[OPT_ARG_ARRAY_SIZE];
985 struct timeval calldurationlimit = { 0, };
986 const char *context;
987 const char *extension;
988 int priority;
989 int bridge_add_failed;
990 int res = -1;
991 struct ast_bridge_features chan_features;
992 struct ast_bridge_features *peer_features;
993 struct ast_bridge *bridge;
994 struct ast_features_xfer_config *xfer_cfg;
995 int noanswer;
996
998 AST_APP_ARG(dest_chan);
1000 );
1001
1002 tmp_data = ast_strdupa(data ?: "");
1003 AST_STANDARD_APP_ARGS(args, tmp_data);
1004 if (!ast_strlen_zero(args.options)) {
1005 ast_app_parse_options(bridge_exec_options, &opts, opt_args, args.options);
1006 }
1007
1008 /* make sure we have a valid end point */
1009 if (!ast_strlen_zero(args.dest_chan)) {
1010 current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
1011 strlen(args.dest_chan));
1012 }
1013 if (!current_dest_chan) {
1014 ast_verb(4, "Bridge failed because channel '%s' does not exist\n",
1015 args.dest_chan ?: "");
1016 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
1017 return 0;
1018 }
1019
1020 /* avoid bridge with ourselves */
1021 if (chan == current_dest_chan) {
1022 ast_channel_unref(current_dest_chan);
1023 ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", ast_channel_name(chan));
1024 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
1025 return 0;
1026 }
1027
1030 && ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
1031 goto done;
1032 }
1033
1038 if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
1040 if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
1046 if (ast_test_flag(&opts, OPT_CALLEE_PARK))
1048 if (ast_test_flag(&opts, OPT_CALLER_PARK))
1051
1052 /* Setup after bridge goto location. */
1053 if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
1054 ast_channel_lock(chan);
1058 ast_channel_unlock(chan);
1060 opt_args[OPT_ARG_CALLEE_GO_ON]);
1061 } else if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
1062 ast_channel_lock(current_dest_chan);
1063 context = ast_strdupa(ast_channel_context(current_dest_chan));
1064 extension = ast_strdupa(ast_channel_exten(current_dest_chan));
1065 priority = ast_channel_priority(current_dest_chan);
1066 ast_channel_unlock(current_dest_chan);
1068 }
1069
1070 if (ast_bridge_features_init(&chan_features)) {
1071 ast_bridge_features_cleanup(&chan_features);
1072 goto done;
1073 }
1074
1075 peer_features = ast_bridge_features_new();
1076 if (!peer_features) {
1077 ast_bridge_features_cleanup(&chan_features);
1078 goto done;
1079 }
1080
1081 if (pre_bridge_setup(chan, current_dest_chan, &bconfig, &chan_features, peer_features, noanswer)) {
1082 ast_bridge_features_destroy(peer_features);
1083 ast_bridge_features_cleanup(&chan_features);
1084 goto done;
1085 }
1086
1087 bridge = ast_bridge_basic_new();
1088 if (!bridge) {
1089 ast_bridge_features_destroy(peer_features);
1090 ast_bridge_features_cleanup(&chan_features);
1091 goto done;
1092 }
1093
1094 ast_channel_lock(current_dest_chan);
1095 xfer_cfg = ast_get_chan_features_xfer_config(current_dest_chan);
1096 ast_channel_unlock(current_dest_chan);
1097 bridge_add_failed = ast_bridge_add_channel(bridge, current_dest_chan, peer_features,
1099 xfer_cfg ? xfer_cfg->xfersound : NULL);
1100 ao2_cleanup(xfer_cfg);
1101 if (bridge_add_failed) {
1102 ast_bridge_features_cleanup(&chan_features);
1103 ast_bridge_destroy(bridge, 0);
1104 goto done;
1105 }
1106
1107 /* Don't keep the channel ref in case it was not already in a bridge. */
1108 current_dest_chan = ast_channel_unref(current_dest_chan);
1109
1110 res = ast_bridge_join(bridge, chan, NULL, &chan_features, NULL,
1112
1113 ast_bridge_features_cleanup(&chan_features);
1114
1115done:
1116 if (res == -1) {
1117 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
1118 } else {
1119 pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
1120 }
1121
1122 ast_free((char *) bconfig.warning_sound);
1123 ast_free((char *) bconfig.end_sound);
1124 ast_free((char *) bconfig.start_sound);
1125
1126 ast_channel_cleanup(current_dest_chan);
1127 return 0;
1128}
1129
1130static int unload_module(void)
1131{
1133
1134 ast_manager_unregister("Bridge");
1135
1137
1138 return 0;
1139}
1140
1141static int load_module(void)
1142{
1143 int res;
1144
1145 res = load_features_config();
1148
1150}
1151
1153 .support_level = AST_MODULE_SUPPORT_CORE,
1154 .load = load_module,
1155 .unload = unload_module,
1157 .load_pri = AST_MODPRI_CORE,
1158 .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
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:1621
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
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
@ AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP
Definition: bridge.h:592
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:590
@ AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP
Definition: bridge.h:537
@ AST_BRIDGE_JOIN_PASS_REFERENCE
Definition: bridge.h:535
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:3412
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3620
int ast_bridge_features_limits_construct(struct ast_bridge_features_limits *limits)
Constructor function for ast_bridge_features_limits.
Definition: bridge.c:3396
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3653
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3674
void ast_bridge_features_limits_destroy(struct ast_bridge_features_limits *limits)
Destructor function for ast_bridge_features_limits.
Definition: bridge.c:3407
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)
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:2385
#define AST_BRIDGE_DTMF_CHANNEL_0
Report DTMF on channel 0.
Definition: channel.h:2370
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:2639
#define DATASTORE_INHERIT_FOREVER
Definition: channel.h:192
#define ast_channel_lock(chan)
Definition: channel.h:2922
@ AST_FEATURE_AUTOMIXMON
Definition: channel.h:1069
@ AST_FEATURE_REDIRECT
Definition: channel.h:1064
@ AST_FEATURE_PARKCALL
Definition: channel.h:1068
@ AST_FEATURE_AUTOMON
Definition: channel.h:1067
@ AST_FEATURE_DISCONNECT
Definition: channel.h:1065
@ AST_FEATURE_PLAY_WARNING
Definition: channel.h:1063
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:1434
#define AST_BRIDGE_DTMF_CHANNEL_1
Report DTMF on channel 1.
Definition: channel.h:2372
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:2958
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1126
#define AST_FEATURE_DTMF_MASK
Definition: channel.h:1072
@ AST_FLAG_IN_AUTOLOOP
Definition: channel.h:997
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:342
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4277
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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:2399
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:442
@ OPT_ARG_CALLEE_GO_ON
Definition: features.c:835
@ OPT_ARG_DURATION_STOP
Definition: features.c:834
@ OPT_ARG_DURATION_LIMIT
Definition: features.c:833
@ OPT_ARG_ARRAY_SIZE
Definition: features.c:837
static const struct ast_app_option bridge_exec_options[128]
Definition: features.c:855
void ast_channel_log(char *title, struct ast_channel *chan)
Definition: features.c:369
static char * app_bridge
Definition: features.c:813
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:497
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
Definition: features.c:428
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:685
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:467
static int action_bridge(struct mansession *s, const struct message *m)
Bridge channels together.
Definition: features.c:726
static int bridge_exec(struct ast_channel *chan, const char *data)
Bridge channels.
Definition: features.c:978
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:595
play_tone_action
Definition: features.c:690
@ PLAYTONE_CHANNEL1
Definition: features.c:692
@ PLAYTONE_CHANNEL2
Definition: features.c:693
@ PLAYTONE_NONE
Definition: features.c:691
@ PLAYTONE_BOTH
Definition: features.c:694
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:857
static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
Definition: features.c:340
static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel *peer)
Definition: features.c:489
static int load_module(void)
Definition: features.c:1141
@ OPT_CALLEE_PARK
Definition: features.c:825
@ OPT_DURATION_LIMIT
Definition: features.c:819
@ OPT_DURATION_STOP
Definition: features.c:820
@ OPT_NOANSWER
Definition: features.c:829
@ OPT_CALLEE_TRANSFER
Definition: features.c:821
@ OPT_CALLEE_GO_ON
Definition: features.c:828
@ OPT_CALLER_PARK
Definition: features.c:826
@ OPT_CALLER_MONITOR
Definition: features.c:824
@ OPT_CALLEE_MONITOR
Definition: features.c:823
@ OPT_CALLER_HANGUP
Definition: features.c:818
@ OPT_CALLEE_HANGUP
Definition: features.c:817
@ BRIDGE_OPT_PLAYTONE
Definition: features.c:816
@ OPT_CALLEE_KILL
Definition: features.c:827
@ OPT_CALLER_TRANSFER
Definition: features.c:822
static enum play_tone_action parse_playtone(const char *playtone_val)
Definition: features.c:697
static void * dial_features_duplicate(void *data)
Definition: features.c:268
static int unload_module(void)
Definition: features.c:1130
static const struct ast_datastore_info dial_features_info
Definition: features.c:281
feature_interpret_op
Definition: features.c:255
@ FEATURE_INTERPRET_CHECK
Definition: features.c:258
@ FEATURE_INTERPRET_DO
Definition: features.c:257
@ FEATURE_INTERPRET_DETECT
Definition: features.c:256
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
Definition: features.c:388
static int add_features_datastore(struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
Definition: features.c:297
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:2471
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:3381
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3413
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3042
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:8041
#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:3056
char * strsep(char **str, const char *delims)
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:202
#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:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
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:103
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CORE
Definition: module.h:324
@ 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:4708
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:1076
const char * end_sound
Definition: channel.h:1087
const char * warning_sound
Definition: channel.h:1086
struct ast_flags features_callee
Definition: channel.h:1078
struct ast_flags features_caller
Definition: channel.h:1077
const char * start_sound
Definition: channel.h:1088
Structure that contains configuration information for the limits feature.
Structure that contains features information.
struct ast_channel * peer
Definition: features.c:336
struct ast_bridge_config bconfig
Definition: features.c:334
struct ast_channel * chan
Definition: features.c:335
unsigned int return_to_pbx
Definition: features.c:337
Structure that contains information about a bridge.
Definition: bridge.h:349
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:265
struct ast_flags my_features
Definition: features.c:263
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:1777
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