Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Enumerations | Functions | Variables
features.c File Reference

Routines implementing call features as call pickup, parking and transfer. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "features_config.h"
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <netinet/in.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/causes.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
#include "asterisk/say.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/utils.h"
#include "asterisk/devicestate.h"
#include "asterisk/audiohook.h"
#include "asterisk/global_datastores.h"
#include "asterisk/astobj2.h"
#include "asterisk/test.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_features.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/bridge_after.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/features_config.h"
#include "asterisk/max_forwards.h"
#include "asterisk/stream.h"

Go to the source code of this file.

Data Structures

struct  ast_bridge_thread_obj
 
struct  ast_dial_features
 

Enumerations

enum  {
  BRIDGE_OPT_PLAYTONE = (1 << 0), OPT_CALLEE_HANGUP = (1 << 1), OPT_CALLER_HANGUP = (1 << 2), OPT_DURATION_LIMIT = (1 << 3),
  OPT_DURATION_STOP = (1 << 4), OPT_CALLEE_TRANSFER = (1 << 5), OPT_CALLER_TRANSFER = (1 << 6), OPT_CALLEE_MONITOR = (1 << 7),
  OPT_CALLER_MONITOR = (1 << 8), OPT_CALLEE_PARK = (1 << 9), OPT_CALLER_PARK = (1 << 10), OPT_CALLEE_KILL = (1 << 11),
  OPT_CALLEE_GO_ON = (1 << 12), OPT_NOANSWER = (1 << 13)
}
 
enum  { OPT_ARG_DURATION_LIMIT = 0, OPT_ARG_DURATION_STOP, OPT_ARG_CALLEE_GO_ON, OPT_ARG_ARRAY_SIZE }
 
enum  feature_interpret_op { FEATURE_INTERPRET_DETECT, FEATURE_INTERPRET_DO, FEATURE_INTERPRET_CHECK }
 
enum  play_tone_action { PLAYTONE_NONE = 0, PLAYTONE_CHANNEL1 = (1 << 0), PLAYTONE_CHANNEL2 = (1 << 1), PLAYTONE_BOTH = PLAYTONE_CHANNEL1 | PLAYTONE_CHANNEL2 }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int action_bridge (struct mansession *s, const struct message *m)
 Bridge channels together. More...
 
static int add_features_datastore (struct ast_channel *chan, const struct ast_flags *my_features, const struct ast_flags *peer_features)
 
static void add_features_datastores (struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
 
int ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
 bridge the call and set CDR More...
 
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. More...
 
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, and timelimit More...
 
void ast_channel_log (char *title, struct ast_channel *chan)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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)
 
static void bridge_config_set_limits_warning_values (struct ast_bridge_config *config, struct ast_bridge_features_limits *limits)
 
static int bridge_exec (struct ast_channel *chan, const char *data)
 Bridge channels. More...
 
static void bridge_failed_peer_goto (struct ast_channel *chan, struct ast_channel *peer)
 
static void * dial_features_duplicate (void *data)
 
static int load_module (void)
 
static enum play_tone_action parse_playtone (const char *playtone_val)
 
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)
 
static void set_bridge_features_on_config (struct ast_bridge_config *config, const char *features)
 
static void set_config_flags (struct ast_channel *chan, struct ast_bridge_config *config)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Call Features" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_features_config, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static char * app_bridge = "Bridge"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_app_option bridge_exec_options [128] = { [ 'p' ] = { .flag = BRIDGE_OPT_PLAYTONE }, [ 'F' ] = { .flag = OPT_CALLEE_GO_ON , .arg_index = OPT_ARG_CALLEE_GO_ON + 1 }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'L' ] = { .flag = OPT_DURATION_LIMIT , .arg_index = OPT_ARG_DURATION_LIMIT + 1 }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'S' ] = { .flag = OPT_DURATION_STOP , .arg_index = OPT_ARG_DURATION_STOP + 1 }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'w' ] = { .flag = OPT_CALLEE_MONITOR }, [ 'W' ] = { .flag = OPT_CALLER_MONITOR }, [ 'x' ] = { .flag = OPT_CALLEE_KILL }, }
 
static const struct ast_datastore_info dial_features_info
 

Detailed Description

Routines implementing call features as call pickup, parking and transfer.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file features.c.

Function Documentation

static int action_bridge ( struct mansession s,
const struct message m 
)
static

Bridge channels together.

Parameters
s
mMake sure valid channels were specified, send errors if any of the channels could not be found/locked, answer channels if needed, create the placeholder channels and grab the other channels make the channels compatible, send error if we fail doing so setup the bridge thread object and start the bridge.
Return values
0

Definition at line 726 of file features.c.

References ast_bridge_add_channel(), ast_bridge_basic_new(), ast_bridge_destroy(), ast_bridge_set_after_goto(), ast_channel_get_by_name_prefix(), ast_debug, AST_FLAG_IN_AUTOLOOP, ast_strdupa, astman_get_header(), astman_send_ack(), astman_send_error(), and RAII_VAR.

727 {
728  const char *channela = astman_get_header(m, "Channel1");
729  const char *channelb = astman_get_header(m, "Channel2");
730  enum play_tone_action playtone = parse_playtone(astman_get_header(m, "Tone"));
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);
764  if (ast_test_flag(ast_channel_flags(chana), AST_FLAG_IN_AUTOLOOP)) {
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);
780  if (ast_test_flag(ast_channel_flags(chanb), AST_FLAG_IN_AUTOLOOP)) {
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 }
Main Channel structure associated with a channel.
Feature configuration relating to transfers.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3421
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
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_debug(level,...)
Log a DEBUG message.
Structure that contains information about a bridge.
Definition: bridge.h:349
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
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
#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
int ast_bridge_call ( struct ast_channel chan,
struct ast_channel peer,
struct ast_bridge_config config 
)

bridge the call and set CDR

Bridge a call, optionally allowing redirection.

Parameters
chanThe bridge considers this channel the caller.
peerThe bridge considers this channel the callee.
configConfiguration for this bridge.

Set start time, check for two channels,check if monitor on check for feature activation, create new CDR

Returns
res on success.
Return values
-1on failure to bridge.

Definition at line 685 of file features.c.

References ast_bridge_call_with_flags().

Referenced by dial_exec_full().

686 {
687  return ast_bridge_call_with_flags(chan, peer, config, 0);
688 }
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
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.

This does the same thing as ast_bridge_call, except that once the bridge is created, the provided flags are set on the bridge. The provided flags are added to the bridge's flags; they will not clear any flags already set.

Parameters
chanThe calling channel
peerThe called channel
configBridge configuration for the channels
flagsAdditional flags to set on the created bridge
Note
The function caller is assumed to have already done the COLP exchange for the initial bridging of the two channels if it was desired.

Definition at line 595 of file features.c.

References ast_bridge_basic_new(), ast_bridge_basic_set_flags(), ast_bridge_destroy(), ast_bridge_features_cleanup(), ast_bridge_features_destroy(), ast_bridge_features_init(), ast_bridge_features_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP, ast_bridge_join(), AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP, AST_BRIDGE_JOIN_PASS_REFERENCE, AST_SOFTHANGUP_ASYNCGOTO, ast_bridge_config::end_bridge_callback, ast_bridge_config::end_bridge_callback_data, and pbx_builtin_getvar_helper().

Referenced by ast_bridge_call().

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);
659  if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
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) {
668  }
669 
670  return res;
671 }
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3653
Structure that contains features information.
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3620
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3674
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 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
void ast_bridge_basic_set_flags(struct ast_bridge *bridge, unsigned int flags)
Set feature flags on a basic bridge.
void * end_bridge_callback_data
Definition: channel.h:1091
Structure that contains information about a bridge.
Definition: bridge.h:349
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
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683
void(* end_bridge_callback)(void *)
Definition: channel.h:1090
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
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, and timelimit

Note
caller must be aware of freeing memory for warning_sound, end_sound, and start_sound

Definition at line 857 of file features.c.

References ast_strdup, ast_strdupa, ast_true(), pbx_builtin_getvar_helper(), and S_OR.

Referenced by bridge_exec(), and dial_exec_full().

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 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
#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
static int bridge_exec ( struct ast_channel chan,
const char *  data 
)
static

Bridge channels.

Parameters
chan
datachannel to bridge with.

Split data, check we aren't bridging with ourself, check valid channel, answer call if not already, check compatible channels, setup bridge config now bridge call, if transferred party hangs up return to PBX extension.

Definition at line 978 of file features.c.

References AST_APP_ARG, ast_app_parse_options(), ast_bridge_add_channel(), ast_bridge_basic_new(), ast_bridge_destroy(), ast_bridge_features_cleanup(), ast_bridge_features_destroy(), ast_bridge_features_init(), ast_bridge_features_new(), ast_bridge_join(), AST_BRIDGE_JOIN_PASS_REFERENCE, ast_bridge_set_after_go_on(), ast_bridge_timelimit(), ast_channel_cleanup, ast_channel_get_by_name_prefix(), ast_channel_unref, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, pbx_builtin_setvar_helper(), and ast_features_xfer_config::xfersound.

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);
999  AST_APP_ARG(options);
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 
1028  if (ast_test_flag(&opts, OPT_DURATION_LIMIT)
1029  && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])
1030  && ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
1031  goto done;
1032  }
1033 
1034  if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
1035  ast_set_flag(&(bconfig.features_callee), AST_FEATURE_REDIRECT);
1036  if (ast_test_flag(&opts, OPT_CALLER_TRANSFER))
1037  ast_set_flag(&(bconfig.features_caller), AST_FEATURE_REDIRECT);
1038  if (ast_test_flag(&opts, OPT_CALLEE_HANGUP))
1039  ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
1040  if (ast_test_flag(&opts, OPT_CALLER_HANGUP))
1041  ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
1042  if (ast_test_flag(&opts, OPT_CALLEE_MONITOR))
1043  ast_set_flag(&(bconfig.features_callee), AST_FEATURE_AUTOMON);
1044  if (ast_test_flag(&opts, OPT_CALLER_MONITOR))
1045  ast_set_flag(&(bconfig.features_caller), AST_FEATURE_AUTOMON);
1046  if (ast_test_flag(&opts, OPT_CALLEE_PARK))
1047  ast_set_flag(&(bconfig.features_callee), AST_FEATURE_PARKCALL);
1048  if (ast_test_flag(&opts, OPT_CALLER_PARK))
1049  ast_set_flag(&(bconfig.features_caller), AST_FEATURE_PARKCALL);
1050  noanswer = ast_test_flag(&opts, OPT_NOANSWER);
1051 
1052  /* Setup after bridge goto location. */
1053  if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
1054  ast_channel_lock(chan);
1055  context = ast_strdupa(ast_channel_context(chan));
1056  extension = ast_strdupa(ast_channel_exten(chan));
1057  priority = ast_channel_priority(chan);
1058  ast_channel_unlock(chan);
1059  ast_bridge_set_after_go_on(current_dest_chan, context, extension, priority,
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);
1067  ast_bridge_set_after_go_on(current_dest_chan, context, extension, priority, NULL);
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,
1098  ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE),
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 
1115 done:
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 }
Main Channel structure associated with a channel.
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3653
Feature configuration relating to transfers.
Structure that contains features information.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3620
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
void ast_bridge_features_destroy(struct ast_bridge_features *features)
Destroy an allocated bridge features struct.
Definition: bridge.c:3674
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_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
bridge configuration
Definition: channel.h:1076
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
structure to hold extensions
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
Structure that contains information about a bridge.
Definition: bridge.h:349
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
Structure used to handle boolean flags.
Definition: utils.h:199
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 pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_bridge_features * ast_bridge_features_new(void)
Allocate a new bridge features struct.
Definition: bridge.c:3683
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, and timelimit
Definition: features.c:857
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
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
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_APP_ARG(name)
Define an application argument.

Variable Documentation

const struct ast_datastore_info dial_features_info
static
Initial value:
= {
.type = "dial-features",
.destroy = ast_free_ptr,
.duplicate = dial_features_duplicate,
}
void ast_free_ptr(void *ptr)
free() wrapper
Definition: main/astmm.c:1739

Definition at line 281 of file features.c.