Files
asterisk/main/features.c

4069 lines
135 KiB
C
Raw Normal View History

/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2008, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Routines implementing call features as call pickup, parking and transfer
*
* \author Mark Spencer <markster@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/_private.h"
#include <pthread.h>
#include <sys/time.h>
#include <sys/signal.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/adsi.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/audiohook.h"
#include "asterisk/global_datastores.h"
#define DEFAULT_PARK_TIME 45000
#define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
2009-02-27 03:52:31 +00:00
#define DEFAULT_FEATURE_DIGIT_TIMEOUT 1000
#define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER 15000
#define DEFAULT_ATXFER_DROP_CALL 0
#define DEFAULT_ATXFER_LOOP_DELAY 10000
#define DEFAULT_ATXFER_CALLBACK_RETRIES 2
#define AST_MAX_WATCHERS 256
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
#define MAX_DIAL_FEATURE_OPTIONS 30
#define FEATURE_RETURN_HANGUP -1
#define FEATURE_RETURN_SUCCESSBREAK 0
#define FEATURE_RETURN_PASSDIGITS 21
#define FEATURE_RETURN_STOREDIGITS 22
#define FEATURE_RETURN_SUCCESS 23
#define FEATURE_RETURN_KEEPTRYING 24
#define FEATURE_RETURN_PARKFAILED 25
enum {
AST_FEATURE_FLAG_NEEDSDTMF = (1 << 0),
AST_FEATURE_FLAG_ONPEER = (1 << 1),
AST_FEATURE_FLAG_ONSELF = (1 << 2),
AST_FEATURE_FLAG_BYCALLEE = (1 << 3),
AST_FEATURE_FLAG_BYCALLER = (1 << 4),
AST_FEATURE_FLAG_BYBOTH = (3 << 3),
};
struct feature_group_exten {
AST_LIST_ENTRY(feature_group_exten) entry;
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(exten);
);
struct ast_call_feature *feature;
};
struct feature_group {
AST_LIST_ENTRY(feature_group) entry;
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(gname);
);
AST_LIST_HEAD_NOLOCK(, feature_group_exten) features;
};
static AST_RWLIST_HEAD_STATIC(feature_groups, feature_group);
static char *parkedcall = "ParkedCall";
static int parkaddhints = 0; /*!< Add parking hints automatically */
static int parkedcalltransfers = 0; /*!< Enable DTMF based transfers on bridge when picking up parked calls */
static int parkedcallreparking = 0; /*!< Enable DTMF based parking on bridge when picking up parked calls */
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
static int parkedcallhangup = 0; /*!< Enable DTMF based disconnect on bridge when picking up parked calls */
static int parkedcallrecording = 0; /*!< Enable DTMF based recording on bridge when picking up parked calls */
static int parkingtime = DEFAULT_PARK_TIME; /*!< No more than 45 seconds parked before you do something with them */
static char parking_con[AST_MAX_EXTENSION]; /*!< Context for which parking is made accessible */
static char parking_con_dial[AST_MAX_EXTENSION]; /*!< Context for dialback for parking (KLUDGE) */
static char parking_ext[AST_MAX_EXTENSION]; /*!< Extension you type to park the call */
static char pickup_ext[AST_MAX_EXTENSION]; /*!< Call pickup extension */
static char parkmohclass[MAX_MUSICCLASS]; /*!< Music class used for parking */
static int parking_start; /*!< First available extension for parking */
static int parking_stop; /*!< Last available extension for parking */
static char courtesytone[256]; /*!< Courtesy tone */
static int parkedplay = 0; /*!< Who to play the courtesy tone to */
static char xfersound[256]; /*!< Call transfer sound */
static char xferfailsound[256]; /*!< Call transfer failure sound */
static int parking_offset;
static int parkfindnext;
static int adsipark;
static int transferdigittimeout;
static int featuredigittimeout;
static int comebacktoorigin = 1;
static int atxfernoanswertimeout;
static unsigned int atxferdropcall;
static unsigned int atxferloopdelay;
static unsigned int atxfercallbackretries;
static char *registrar = "features"; /*!< Registrar for operations */
/* module and CLI command definitions */
static char *synopsis = "Answer a parked call";
static char *descrip = "ParkedCall(exten): "
"Used to connect to a parked call. This application is always\n"
"registered internally and does not need to be explicitly added\n"
"into the dialplan, although you should include the 'parkedcalls'\n"
"context. If no extension is provided, then the first available\n"
"parked call will be acquired.\n";
static char *parkcall = "Park";
static char *synopsis2 = "Park yourself";
static char *descrip2 = "Park(): "
"Used to park yourself (typically in combination with a supervised\n"
"transfer to know the parking space). This application is always\n"
"registered internally and does not need to be explicitly added\n"
"into the dialplan, although you should include the 'parkedcalls'\n"
"context (or the context specified in features.conf).\n\n"
"If you set the PARKINGEXTEN variable to an extension in your\n"
"parking context, Park() will park the call on that extension, unless\n"
"it already exists. In that case, execution will continue at next\n"
"priority.\n" ;
static struct ast_app *monitor_app = NULL;
static int monitor_ok = 1;
static struct ast_app *mixmonitor_app = NULL;
static int mixmonitor_ok = 1;
static struct ast_app *stopmixmonitor_app = NULL;
static int stopmixmonitor_ok = 1;
struct parkeduser {
struct ast_channel *chan; /*!< Parking channel */
struct timeval start; /*!< Time the parking started */
int parkingnum; /*!< Parking lot */
char parkingexten[AST_MAX_EXTENSION]; /*!< If set beforehand, parking extension used for this call */
char context[AST_MAX_CONTEXT]; /*!< Where to go if our parking time expires */
char exten[AST_MAX_EXTENSION];
int priority;
int parkingtime; /*!< Maximum length in parking lot before return */
int notquiteyet;
char peername[1024];
unsigned char moh_trys;
AST_LIST_ENTRY(parkeduser) list;
};
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
struct ast_dial_features {
struct ast_flags features_caller;
struct ast_flags features_callee;
int is_caller;
};
static AST_LIST_HEAD_STATIC(parkinglot, parkeduser);
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
static void *dial_features_duplicate(void *data)
{
struct ast_dial_features *df = data, *df_copy;
if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
return NULL;
}
memcpy(df_copy, df, sizeof(*df));
return df_copy;
}
static void dial_features_destroy(void *data)
{
struct ast_dial_features *df = data;
if (df) {
ast_free(df);
}
}
const struct ast_datastore_info dial_features_info = {
.type = "dial-features",
.destroy = dial_features_destroy,
.duplicate = dial_features_duplicate,
};
static pthread_t parking_thread;
const char *ast_parking_ext(void)
{
return parking_ext;
}
const char *ast_pickup_ext(void)
{
return pickup_ext;
}
struct ast_bridge_thread_obj
{
struct ast_bridge_config bconfig;
struct ast_channel *chan;
struct ast_channel *peer;
unsigned int return_to_pbx:1;
};
/*!
* \brief store context, extension and priority
* \param chan, context, ext, pri
*/
static void set_c_e_p(struct ast_channel *chan, const char *context, const char *ext, int pri)
{
ast_copy_string(chan->context, context, sizeof(chan->context));
ast_copy_string(chan->exten, ext, sizeof(chan->exten));
chan->priority = pri;
}
/*!
* \brief Check goto on transfer
* \param chan
*
* Check if channel has 'GOTO_ON_BLINDXFR' set, if not exit.
* When found make sure the types are compatible. Check if channel is valid
* if so start the new channel else hangup the call.
*/
static void check_goto_on_transfer(struct ast_channel *chan)
{
struct ast_channel *xferchan;
const char *val = pbx_builtin_getvar_helper(chan, "GOTO_ON_BLINDXFR");
char *x, *goto_on_transfer;
struct ast_frame *f;
if (ast_strlen_zero(val))
return;
goto_on_transfer = ast_strdupa(val);
if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "%s", chan->name)))
return;
for (x = goto_on_transfer; x && *x; x++) {
if (*x == '^')
*x = '|';
}
/* Make formats okay */
xferchan->readformat = chan->readformat;
xferchan->writeformat = chan->writeformat;
ast_channel_masquerade(xferchan, chan);
ast_parseable_goto(xferchan, goto_on_transfer);
xferchan->_state = AST_STATE_UP;
ast_clear_flag(xferchan, AST_FLAGS_ALL);
xferchan->_softhangup = 0;
if ((f = ast_read(xferchan))) {
ast_frfree(f);
f = NULL;
ast_pbx_start(xferchan);
} else {
ast_hangup(xferchan);
}
}
static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language);
/*!
* \brief bridge the call
* \param data thread bridge.
*
* Set Last Data for respective channels, reset cdr for channels
* bridge call, check if we're going back to dialplan
* if not hangup both legs of the call
*/
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
static void *ast_bridge_call_thread(void *data)
{
struct ast_bridge_thread_obj *tobj = data;
int res;
tobj->chan->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
tobj->chan->data = tobj->peer->name;
tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
tobj->peer->data = tobj->chan->name;
ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
if (tobj->return_to_pbx) {
if (!ast_check_hangup(tobj->peer)) {
ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", tobj->peer->name);
res = ast_pbx_start(tobj->peer);
if (res != AST_PBX_SUCCESS)
ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", tobj->peer->name);
} else
ast_hangup(tobj->peer);
if (!ast_check_hangup(tobj->chan)) {
ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", tobj->chan->name);
res = ast_pbx_start(tobj->chan);
if (res != AST_PBX_SUCCESS)
ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", tobj->chan->name);
} else
ast_hangup(tobj->chan);
} else {
ast_hangup(tobj->chan);
ast_hangup(tobj->peer);
}
ast_free(tobj);
return NULL;
}
/*!
* \brief create thread for the parked call
* \param data
*
* Create thread and attributes, call ast_bridge_call_thread
*/
static void ast_bridge_call_thread_launch(void *data)
{
pthread_t thread;
pthread_attr_t attr;
struct sched_param sched;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ast_pthread_create(&thread, &attr,ast_bridge_call_thread, data);
pthread_attr_destroy(&attr);
memset(&sched, 0, sizeof(sched));
pthread_setschedparam(thread, SCHED_RR, &sched);
}
/*!
* \brief Announce call parking by ADSI
* \param chan .
* \param parkingexten .
* Create message to show for ADSI, display message.
* \retval 0 on success.
* \retval -1 on failure.
*/
static int adsi_announce_park(struct ast_channel *chan, char *parkingexten)
{
int res;
int justify[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
char tmp[256];
char *message[5] = {NULL, NULL, NULL, NULL, NULL};
snprintf(tmp, sizeof(tmp), "Parked on %s", parkingexten);
message[0] = tmp;
res = ast_adsi_load_session(chan, NULL, 0, 1);
if (res == -1)
return res;
return ast_adsi_print(chan, message, justify, 1);
}
/*! \brief Notify metermaids that we've changed an extension */
static void notify_metermaids(const char *exten, char *context, enum ast_device_state state)
{
ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'",
exten, context, devstate2str(state));
ast_devstate_changed(state, "park:%s@%s", exten, context);
}
/*! \brief metermaids callback from devicestate.c */
static enum ast_device_state metermaidstate(const char *data)
{
char *context;
char *exten;
context = ast_strdupa(data);
exten = strsep(&context, "@");
if (!context)
return AST_DEVICE_INVALID;
ast_debug(4, "Checking state of exten %s in context %s\n", exten, context);
if (!ast_exists_extension(NULL, context, exten, 1, NULL))
return AST_DEVICE_NOT_INUSE;
return AST_DEVICE_INUSE;
}
static struct parkeduser *park_space_reserve(struct ast_channel *chan)
{
struct parkeduser *pu, *cur;
int i, parking_space = -1, parking_range;
const char *parkingexten;
/* Allocate memory for parking data */
if (!(pu = ast_calloc(1, sizeof(*pu))))
return NULL;
/* Lock parking lot */
AST_LIST_LOCK(&parkinglot);
/* Check for channel variable PARKINGEXTEN */
parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
if (!ast_strlen_zero(parkingexten)) {
/*!\note The API forces us to specify a numeric parking slot, even
* though the architecture would tend to support non-numeric extensions
* (as are possible with SIP, for example). Hence, we enforce that
* limitation here. If extout was not numeric, we could permit
* arbitrary non-numeric extensions.
*/
if (sscanf(parkingexten, "%30d", &parking_space) != 1 || parking_space < 0) {
AST_LIST_UNLOCK(&parkinglot);
ast_free(pu);
ast_log(LOG_WARNING, "PARKINGEXTEN does not indicate a valid parking slot: '%s'.\n", parkingexten);
return NULL;
}
snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
if (ast_exists_extension(NULL, parking_con, pu->parkingexten, 1, NULL)) {
AST_LIST_UNLOCK(&parkinglot);
ast_free(pu);
ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
return NULL;
}
} else {
/* Select parking space within range */
parking_range = parking_stop - parking_start+1;
for (i = 0; i < parking_range; i++) {
parking_space = (i + parking_offset) % parking_range + parking_start;
AST_LIST_TRAVERSE(&parkinglot, cur, list) {
if (cur->parkingnum == parking_space)
break;
}
if (!cur)
break;
}
if (!(i < parking_range)) {
ast_log(LOG_WARNING, "No more parking spaces\n");
ast_free(pu);
AST_LIST_UNLOCK(&parkinglot);
return NULL;
}
/* Set pointer for next parking */
if (parkfindnext)
parking_offset = parking_space - parking_start + 1;
snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", parking_space);
}
pu->notquiteyet = 1;
pu->parkingnum = parking_space;
AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
AST_LIST_UNLOCK(&parkinglot);
return pu;
}
/* Park a call */
static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout, const char *orig_chan_name, struct parkeduser *pu)
{
struct ast_context *con;
const char *event_from;
/* Get a valid space if not already done */
if (pu == NULL)
pu = park_space_reserve(chan);
if (pu == NULL)
return 1; /* Continue execution if possible */
snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", pu->parkingnum);
chan->appl = "Parked Call";
chan->data = NULL;
pu->chan = chan;
/* Put the parked channel on hold if we have two different channels */
if (chan != peer) {
ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
S_OR(parkmohclass, NULL),
!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
}
pu->start = ast_tvnow();
pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
if (extout)
*extout = pu->parkingnum;
if (peer) {
/* This is so ugly that it hurts, but implementing get_base_channel() on local channels
could have ugly side effects. We could have transferer<->local,1<->local,2<->parking
and we need the callback name to be that of transferer. Since local,1/2 have the same
name we can be tricky and just grab the bridged channel from the other side of the local
*/
if (!strcasecmp(peer->tech->type, "Local")) {
struct ast_channel *tmpchan, *base_peer;
char other_side[AST_CHANNEL_NAME];
char *c;
ast_copy_string(other_side, S_OR(orig_chan_name, peer->name), sizeof(other_side));
if ((c = strrchr(other_side, ';'))) {
*++c = '1';
}
if ((tmpchan = ast_get_channel_by_name_locked(other_side))) {
if ((base_peer = ast_bridged_channel(tmpchan))) {
ast_copy_string(pu->peername, base_peer->name, sizeof(pu->peername));
}
ast_channel_unlock(tmpchan);
}
} else {
ast_copy_string(pu->peername, S_OR(orig_chan_name, peer->name), sizeof(pu->peername));
}
}
/* Remember what had been dialed, so that if the parking
expires, we try to come back to the same place */
ast_copy_string(pu->context, S_OR(chan->macrocontext, chan->context), sizeof(pu->context));
ast_copy_string(pu->exten, S_OR(chan->macroexten, chan->exten), sizeof(pu->exten));
pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
/* If parking a channel directly, don't quiet yet get parking running on it.
* All parking lot entries are put into the parking lot with notquiteyet on. */
if (peer != chan)
pu->notquiteyet = 0;
/* Wake up the (presumably select()ing) thread */
pthread_kill(parking_thread, SIGURG);
ast_verb(2, "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
if (peer) {
event_from = peer->name;
} else {
event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
}
manager_event(EVENT_FLAG_CALL, "ParkedCall",
"Exten: %s\r\n"
"Channel: %s\r\n"
"From: %s\r\n"
"Timeout: %ld\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
"Uniqueid: %s\r\n",
pu->parkingexten, pu->chan->name, event_from ? event_from : "",
(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
S_OR(pu->chan->cid.cid_num, "<unknown>"),
S_OR(pu->chan->cid.cid_name, "<unknown>"),
pu->chan->uniqueid
);
if (peer && adsipark && ast_adsi_available(peer)) {
adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
ast_adsi_unload_session(peer);
}
Merged revisions 130145 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Merging this rev from trunk to 1.6.0 was not simple. Why? Because we've enhanced trunk to do a [fast] merge-and-delete operation which also solved problems with contexts having entries from different registrars. Fast as in the amount of time the contexts are locked down. That *is* fast, but traversing the entire dialplan looking for priorities to delete takes more time overall. This particular fix involved pulling in those enhancements from trunk, along with all the various fixes and refinements made along the way. Merging all this from trunk into 1.6 involved: a. mergetrunk6 in the stuff from 130145; b. revert all but the prop changes c. catalog all revisions to pbx.c since 1.6.0 was forked (at rev 105596). d. catalog all revisions to pbx.c in trunk since 1.6.0 was forked, making special note of all revs that were not merged into 1.6.0. e. study each rev in trunk not applied to 1.6.0, and determine if it was involved in the merge_and_delete enhancements in trunk. 25 commits were done in 1.6.0, all but one (106306) was a merge from trunk. Trunk had 22 additional changes, of which 7 were involved in the merge_and_delete enhancements: 106757 108894 109169 116461 123358 130145 130297 f. Go to trunk and collect patches, one by one, of the changes made by each rev across the entire source tree, using svn diff -c <num> > pfile g. Apply each patch in order to 1.6.0, and resolve all failures and compilation problems before proceding to the next patch. h. test the stuff. i. profit! ........ r130145 | murf | 2008-07-11 12:24:31 -0600 (Fri, 11 Jul 2008) | 40 lines (closes issue #13041) Reported by: eliel Tested by: murf (closes issue #12960) Reported by: mnicholson In this 'omnibus' fix, I **think** I solved both the problem in 13041, where unloading pbx_ael.so caused crashes, or incomplete removal of previous registrar'ed entries. And I added code to completely remove all includes, switches, and ignorepats that had a matching registrar entry, which should appease 12960. I also added a lot of seemingly useless brackets around single statement if's, which helped debug so much that I'm leaving them there. I added a routine to check the correlation between the extension tree lists and the hashtab tables. It can be amazingly helpful when you have lots of dialplan stuff, and need to narrow down where a problem is occurring. It's ifdef'd out by default. I cleaned up the code around the new CIDmatch code. It was leaving hanging extens with bad ptrs, getting confused over which objects to remove, etc. I tightened up the code and changed the call to remove_exten in the merge_and_delete code. I added more conditions to check for empty context worthy of deletion. It's not empty if there are any includes, switches, or ignorepats present. If I've missed anything, please re-open this bug, and be prepared to supply example dialplan code. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@130946 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-07-15 13:14:07 +00:00
con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
if (!con) /* Still no context? Bad */
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
if (con) {
if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
}
/* Tell the peer channel the number of the parking space */
if (peer && (ast_strlen_zero(orig_chan_name) || !strcasecmp(peer->name, orig_chan_name))) { /* Only say number if it's a number and the channel hasn't been masqueraded away */
/* If a channel is masqueraded into peer while playing back the parking slot number do not continue playing it back. This is the case if an attended transfer occurs. */
ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
ast_say_digits(peer, pu->parkingnum, "", peer->language);
ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
}
if (pu->notquiteyet) {
/* Wake up parking thread if we're really done */
ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
S_OR(parkmohclass, NULL),
!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
pu->notquiteyet = 0;
pthread_kill(parking_thread, SIGURG);
}
return 0;
}
/*! \brief Park a call */
int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeout, int *extout)
{
return park_call_full(chan, peer, timeout, extout, NULL, NULL);
}
static int masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, int play_announcement, const char *orig_chan_name)
{
struct ast_channel *chan;
struct ast_frame *f;
struct parkeduser *pu;
int park_status;
if ((pu = park_space_reserve(rchan)) == NULL) {
if (peer)
ast_stream_and_wait(peer, "beeperr", "");
return FEATURE_RETURN_PARKFAILED;
}
/* Make a new, fake channel that we'll use to masquerade in the real one */
if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
ast_log(LOG_WARNING, "Unable to create parked channel\n");
return -1;
}
/* Make formats okay */
chan->readformat = rchan->readformat;
chan->writeformat = rchan->writeformat;
ast_channel_masquerade(chan, rchan);
/* Setup the extensions and such */
set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
/* Make the masq execute */
if ((f = ast_read(chan)))
ast_frfree(f);
if (peer == rchan) {
peer = chan;
}
if (!play_announcement && !orig_chan_name) {
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
orig_chan_name = ast_strdupa(chan->name);
}
park_status = park_call_full(chan, peer, timeout, extout, orig_chan_name, pu);
if (park_status == 1) {
/* would be nice to play "invalid parking extension" */
ast_hangup(chan);
return -1;
}
return 0;
}
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
/* Park call via masquraded channel */
int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout)
{
return masq_park_call(rchan, peer, timeout, extout, 0, NULL);
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
}
static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, const char *orig_chan_name)
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
{
return masq_park_call(rchan, peer, timeout, extout, 1, orig_chan_name);
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
}
/*!
* \brief set caller and callee according to the direction
* \param caller, callee, peer, chan, sense
*
* Detect who triggered feature and set callee/caller variables accordingly
*/
static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
struct ast_channel *peer, struct ast_channel *chan, int sense)
{
if (sense == FEATURE_SENSE_PEER) {
*caller = peer;
*callee = chan;
} else {
*callee = peer;
*caller = chan;
}
}
/*!
* \brief support routing for one touch call parking
* \param chan channel parking call
* \param peer channel to be parked
* \param config unsed
* \param code unused
* \param sense feature options
*
* \param data
* Setup channel, set return exten,priority to 's,1'
* answer chan, sleep chan, park call
*/
static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
struct ast_channel *parker;
struct ast_channel *parkee;
int res = 0;
set_peers(&parker, &parkee, peer, chan, sense);
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
/* we used to set chan's exten and priority to "s" and 1
here, but this generates (in some cases) an invalid
extension, and if "s" exists, could errantly
cause execution of extensions you don't expect. It
makes more sense to let nature take its course
when chan finishes, and let the pbx do its thing
and hang up when the park is over.
*/
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_safe_sleep(chan, 1000);
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
if (!res) { /* one direction used to call park_call.... */
res = masq_park_call_announce(parkee, parker, 0, NULL, NULL);
/* PBX should hangup zombie channel if a masquerade actually occurred (res=0) */
}
return res;
}
/*!
* \brief Monitor a channel by DTMF
* \param chan channel requesting monitor
* \param peer channel to be monitored
* \param config
* \param code
* \param sense feature options
*
* \param data
* Check monitor app enabled, setup channels, both caller/callee chans not null
* get TOUCH_MONITOR variable for filename if exists, exec monitor app.
* \retval FEATURE_RETURN_SUCCESS on success.
* \retval -1 on error.
*/
static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
int x = 0;
size_t len;
struct ast_channel *caller_chan, *callee_chan;
if (!monitor_ok) {
ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
return -1;
}
if (!monitor_app && !(monitor_app = pbx_findapp("Monitor"))) {
monitor_ok = 0;
ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
return -1;
}
set_peers(&caller_chan, &callee_chan, peer, chan, sense);
if (!ast_strlen_zero(courtesytone)) {
if (ast_autoservice_start(callee_chan))
return -1;
if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
ast_autoservice_stop(callee_chan);
return -1;
}
if (ast_autoservice_stop(callee_chan))
return -1;
}
if (callee_chan->monitor) {
ast_verb(4, "User hit '%s' to stop recording call.\n", code);
callee_chan->monitor->stop(callee_chan, 1);
return FEATURE_RETURN_SUCCESS;
}
if (caller_chan && callee_chan) {
const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
const char *touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
if (!touch_format)
touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
if (!touch_monitor)
touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
if (!touch_monitor_prefix)
touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
if (touch_monitor) {
len = strlen(touch_monitor) + 50;
args = alloca(len);
touch_filename = alloca(len);
snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
} else {
caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
args = alloca(len);
touch_filename = alloca(len);
snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
}
for(x = 0; x < strlen(args); x++) {
if (args[x] == '/')
args[x] = '-';
}
ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
pbx_exec(callee_chan, monitor_app, args);
pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
return FEATURE_RETURN_SUCCESS;
}
ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
return -1;
}
static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
int x = 0;
size_t len;
struct ast_channel *caller_chan, *callee_chan;
const char *mixmonitor_spy_type = "MixMonitor";
int count = 0;
if (!mixmonitor_ok) {
ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
return -1;
}
if (!(mixmonitor_app = pbx_findapp("MixMonitor"))) {
mixmonitor_ok = 0;
ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
return -1;
}
set_peers(&caller_chan, &callee_chan, peer, chan, sense);
if (!ast_strlen_zero(courtesytone)) {
if (ast_autoservice_start(callee_chan))
return -1;
if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
ast_autoservice_stop(callee_chan);
return -1;
}
if (ast_autoservice_stop(callee_chan))
return -1;
}
ast_channel_lock(callee_chan);
count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
ast_channel_unlock(callee_chan);
// This means a mixmonitor is attached to the channel, running or not is unknown.
if (count > 0) {
ast_verb(3, "User hit '%s' to stop recording call.\n", code);
//Make sure they are running
ast_channel_lock(callee_chan);
count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
ast_channel_unlock(callee_chan);
if (count > 0) {
if (!stopmixmonitor_ok) {
ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
return -1;
}
if (!(stopmixmonitor_app = pbx_findapp("StopMixMonitor"))) {
stopmixmonitor_ok = 0;
ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
return -1;
} else {
pbx_exec(callee_chan, stopmixmonitor_app, "");
return FEATURE_RETURN_SUCCESS;
}
}
ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
}
if (caller_chan && callee_chan) {
const char *touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
const char *touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
if (!touch_format)
touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
if (!touch_monitor)
touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
if (touch_monitor) {
len = strlen(touch_monitor) + 50;
args = alloca(len);
touch_filename = alloca(len);
snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
} else {
caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
args = alloca(len);
touch_filename = alloca(len);
snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
}
for( x = 0; x < strlen(args); x++) {
if (args[x] == '/')
args[x] = '-';
}
ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
pbx_exec(callee_chan, mixmonitor_app, args);
pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
return FEATURE_RETURN_SUCCESS;
}
ast_log(LOG_NOTICE,"Cannot record the call. One or both channels have gone away.\n");
return -1;
}
static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
ast_verb(4, "User hit '%s' to disconnect call.\n", code);
return FEATURE_RETURN_HANGUP;
}
static int finishup(struct ast_channel *chan)
{
ast_indicate(chan, AST_CONTROL_UNHOLD);
return ast_autoservice_stop(chan);
}
/*!
* \brief Find the context for the transfer
* \param transferer
* \param transferee
*
* Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
* \return a context string
*/
static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
{
const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
if (ast_strlen_zero(s)) {
s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
}
if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
s = transferer->macrocontext;
}
if (ast_strlen_zero(s)) {
s = transferer->context;
}
return s;
}
/*!
* \brief Blind transfer user to another extension
* \param chan channel to be transfered
* \param peer channel initiated blind transfer
* \param config
* \param code
* \param data
* \param sense feature options
*
* Place chan on hold, check if transferred to parkinglot extension,
* otherwise check extension exists and transfer caller.
* \retval FEATURE_RETURN_SUCCESS.
* \retval -1 on failure.
*/
static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
struct ast_channel *transferer;
struct ast_channel *transferee;
const char *transferer_real_context;
char xferto[256];
int res;
int parkstatus = 0;
set_peers(&transferer, &transferee, peer, chan, sense);
transferer_real_context = real_ctx(transferer, transferee);
/* Start autoservice on chan while we talk to the originator */
ast_autoservice_start(transferee);
ast_indicate(transferee, AST_CONTROL_HOLD);
memset(xferto, 0, sizeof(xferto));
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
/* Transfer */
res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
if (res < 0) {
finishup(transferee);
return -1; /* error ? */
}
if (res > 0) /* If they've typed a digit already, handle it */
xferto[0] = (char) res;
ast_stopstream(transferer);
res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
finishup(transferee);
return res;
}
if (!strcmp(xferto, ast_parking_ext())) {
res = finishup(transferee);
if (res)
res = -1;
else if (!(parkstatus = masq_park_call_announce(transferee, transferer, 0, NULL, NULL))) { /* success */
/* We return non-zero, but tell the PBX not to hang the channel when
the thread dies -- We have to be careful now though. We are responsible for
hanging up the channel, else it will never be hung up! */
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
return 0;
} else {
ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
}
/*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
} else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
res=finishup(transferee);
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
if (!transferer->cdr) { /* this code should never get called (in a perfect world) */
transferer->cdr=ast_cdr_alloc();
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
if (transferer->cdr) {
ast_cdr_init(transferer->cdr, transferer); /* initialize our channel's cdr */
ast_cdr_start(transferer->cdr);
}
}
if (transferer->cdr) {
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
struct ast_cdr *swap = transferer->cdr;
ast_log(LOG_DEBUG,"transferer=%s; transferee=%s; lastapp=%s; lastdata=%s; chan=%s; dstchan=%s\n",
transferer->name, transferee->name, transferer->cdr->lastapp, transferer->cdr->lastdata,
transferer->cdr->channel, transferer->cdr->dstchannel);
ast_log(LOG_DEBUG,"TRANSFEREE; lastapp=%s; lastdata=%s, chan=%s; dstchan=%s\n",
transferee->cdr->lastapp, transferee->cdr->lastdata, transferee->cdr->channel, transferee->cdr->dstchannel);
ast_log(LOG_DEBUG,"transferer_real_context=%s; xferto=%s\n", transferer_real_context, xferto);
/* swap cdrs-- it will save us some time & work */
transferer->cdr = transferee->cdr;
transferee->cdr = swap;
}
if (!transferee->pbx) {
/* Doh! Use our handy async_goto functions */
ast_verb(3, "Transferring %s to '%s' (context %s) priority 1\n"
,transferee->name, xferto, transferer_real_context);
if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
ast_log(LOG_WARNING, "Async goto failed :-(\n");
} else {
/* Set the channel's new extension, since it exists, using transferer context */
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
set_c_e_p(transferee, transferer_real_context, xferto, 0);
}
check_goto_on_transfer(transferer);
return res;
} else {
ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
}
if (parkstatus != FEATURE_RETURN_PARKFAILED && ast_stream_and_wait(transferer, xferfailsound, AST_DIGIT_ANY) < 0) {
finishup(transferee);
return -1;
}
ast_stopstream(transferer);
res = finishup(transferee);
if (res) {
ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
return res;
}
return FEATURE_RETURN_SUCCESS;
}
/*!
* \brief make channels compatible
* \param c
* \param newchan
* \retval 0 on success.
* \retval -1 on failure.
*/
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
{
if (ast_channel_make_compatible(c, newchan) < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
c->name, newchan->name);
ast_hangup(newchan);
return -1;
}
return 0;
}
/*!
* \brief Attended transfer
* \param chan transfered user
* \param peer person transfering call
* \param config
* \param code
* \param sense feature options
*
* \param data
* Get extension to transfer to, if you cannot generate channel (or find extension)
* return to host channel. After called channel answered wait for hangup of transferer,
* bridge call between transfer peer (taking them off hold) to attended transfer channel.
*
* \return -1 on failure
*/
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
struct ast_channel *transferer;
struct ast_channel *transferee;
const char *transferer_real_context;
char xferto[256] = "";
int res;
int outstate=0;
struct ast_channel *newchan;
struct ast_channel *xferchan;
struct ast_bridge_thread_obj *tobj;
struct ast_bridge_config bconfig;
struct ast_frame *f;
int l;
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures = NULL;
ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
set_peers(&transferer, &transferee, peer, chan, sense);
transferer_real_context = real_ctx(transferer, transferee);
/* Start autoservice on chan while we talk to the originator */
ast_autoservice_start(transferee);
ast_indicate(transferee, AST_CONTROL_HOLD);
/* Transfer */
res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
if (res < 0) {
finishup(transferee);
return res;
}
if (res > 0) /* If they've typed a digit already, handle it */
xferto[0] = (char) res;
/* this is specific of atxfer */
res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
if (res < 0) { /* hangup, would be 0 for invalid and 1 for valid */
finishup(transferee);
return res;
}
if (res == 0) {
ast_log(LOG_WARNING, "Did not read data.\n");
finishup(transferee);
if (ast_stream_and_wait(transferer, "beeperr", ""))
return -1;
return FEATURE_RETURN_SUCCESS;
}
/* valid extension, res == 1 */
if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
finishup(transferee);
if (ast_stream_and_wait(transferer, "beeperr", ""))
return -1;
return FEATURE_RETURN_SUCCESS;
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
/* If we are attended transfering to parking, just use builtin_parkcall instead of trying to track all of
* the different variables for handling this properly with a builtin_atxfer */
if (!strcmp(xferto, ast_parking_ext())) {
finishup(transferee);
return builtin_parkcall(chan, peer, config, code, sense, data);
}
l = strlen(xferto);
snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
if (!ast_check_hangup(transferer)) {
/* Transferer is up - old behaviour */
ast_indicate(transferer, -1);
if (!newchan) {
finishup(transferee);
/* any reason besides user requested cancel and busy triggers the failed sound */
if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY &&
ast_stream_and_wait(transferer, xferfailsound, ""))
return -1;
if (ast_stream_and_wait(transferer, xfersound, ""))
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
return FEATURE_RETURN_SUCCESS;
}
if (check_compat(transferer, newchan)) {
/* we do mean transferee here, NOT transferer */
finishup(transferee);
return -1;
}
memset(&bconfig,0,sizeof(struct ast_bridge_config));
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
res = ast_bridge_call(transferer, newchan, &bconfig);
if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
ast_hangup(newchan);
if (ast_stream_and_wait(transferer, xfersound, ""))
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
finishup(transferee);
transferer->_softhangup = 0;
return FEATURE_RETURN_SUCCESS;
}
if (check_compat(transferee, newchan)) {
finishup(transferee);
return -1;
}
ast_indicate(transferee, AST_CONTROL_UNHOLD);
if ((ast_autoservice_stop(transferee) < 0)
|| (ast_waitfordigit(transferee, 100) < 0)
|| (ast_waitfordigit(newchan, 100) < 0)
|| ast_check_hangup(transferee)
|| ast_check_hangup(newchan)) {
ast_hangup(newchan);
return -1;
}
xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
if (!xferchan) {
ast_hangup(newchan);
return -1;
}
/* Make formats okay */
xferchan->visible_indication = transferer->visible_indication;
xferchan->readformat = transferee->readformat;
xferchan->writeformat = transferee->writeformat;
ast_channel_masquerade(xferchan, transferee);
ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
xferchan->_state = AST_STATE_UP;
ast_clear_flag(xferchan, AST_FLAGS_ALL);
xferchan->_softhangup = 0;
if ((f = ast_read(xferchan)))
ast_frfree(f);
newchan->_state = AST_STATE_UP;
ast_clear_flag(newchan, AST_FLAGS_ALL);
newchan->_softhangup = 0;
if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
ast_hangup(xferchan);
ast_hangup(newchan);
return -1;
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
ast_channel_lock(newchan);
if ((features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL))) {
dialfeatures = features_datastore->data;
}
ast_channel_unlock(newchan);
if (dialfeatures) {
/* newchan should always be the callee and shows up as callee in dialfeatures, but for some reason
I don't currently understand, the abilities of newchan seem to be stored on the caller side */
ast_copy_flags(&(config->features_callee), &(dialfeatures->features_caller), AST_FLAGS_ALL);
dialfeatures = NULL;
}
ast_channel_lock(xferchan);
if ((features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL))) {
dialfeatures = features_datastore->data;
}
ast_channel_unlock(xferchan);
if (dialfeatures) {
ast_copy_flags(&(config->features_caller), &(dialfeatures->features_caller), AST_FLAGS_ALL);
}
tobj->chan = newchan;
tobj->peer = xferchan;
tobj->bconfig = *config;
if (tobj->bconfig.end_bridge_callback_data_fixup) {
tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
}
if (ast_stream_and_wait(newchan, xfersound, ""))
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
ast_bridge_call_thread_launch(tobj);
return -1; /* XXX meaning the channel is bridged ? */
} else if (!ast_check_hangup(transferee)) {
/* act as blind transfer */
if (ast_autoservice_stop(transferee) < 0) {
ast_hangup(newchan);
return -1;
}
if (!newchan) {
unsigned int tries = 0;
char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
transferer_tech = strsep(&transferer_name, "/");
transferer_name = strsep(&transferer_name, "-");
if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
if (ast_stream_and_wait(transferee, "beeperr", ""))
return -1;
return FEATURE_RETURN_SUCCESS;
}
ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
/* Trying to transfer again */
ast_autoservice_start(transferee);
ast_indicate(transferee, AST_CONTROL_HOLD);
newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
if (ast_autoservice_stop(transferee) < 0) {
if (newchan)
ast_hangup(newchan);
return -1;
}
if (!newchan) {
/* Transfer failed, sleeping */
ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
ast_safe_sleep(transferee, atxferloopdelay);
ast_debug(1, "Trying to callback...\n");
newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
}
tries++;
}
}
if (!newchan)
return -1;
/* newchan is up, we should prepare transferee and bridge them */
if (check_compat(transferee, newchan)) {
finishup(transferee);
return -1;
}
ast_indicate(transferee, AST_CONTROL_UNHOLD);
if ((ast_waitfordigit(transferee, 100) < 0)
|| (ast_waitfordigit(newchan, 100) < 0)
|| ast_check_hangup(transferee)
|| ast_check_hangup(newchan)) {
ast_hangup(newchan);
return -1;
}
xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
if (!xferchan) {
ast_hangup(newchan);
return -1;
}
/* Make formats okay */
xferchan->visible_indication = transferer->visible_indication;
xferchan->readformat = transferee->readformat;
xferchan->writeformat = transferee->writeformat;
ast_channel_masquerade(xferchan, transferee);
ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
xferchan->_state = AST_STATE_UP;
ast_clear_flag(xferchan, AST_FLAGS_ALL);
xferchan->_softhangup = 0;
if ((f = ast_read(xferchan)))
ast_frfree(f);
newchan->_state = AST_STATE_UP;
ast_clear_flag(newchan, AST_FLAGS_ALL);
newchan->_softhangup = 0;
if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
ast_hangup(xferchan);
ast_hangup(newchan);
return -1;
}
tobj->chan = newchan;
tobj->peer = xferchan;
tobj->bconfig = *config;
if (tobj->bconfig.end_bridge_callback_data_fixup) {
tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
}
if (ast_stream_and_wait(newchan, xfersound, ""))
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
ast_bridge_call_thread_launch(tobj);
return -1; /* XXX meaning the channel is bridged ? */
} else {
/* Transferee hung up */
finishup(transferee);
return -1;
}
}
/* add atxfer and automon as undefined so you can only use em if you configure them */
#define FEATURES_COUNT ARRAY_LEN(builtin_features)
AST_RWLOCK_DEFINE_STATIC(features_lock);
static struct ast_call_feature builtin_features[] =
{
{ AST_FEATURE_REDIRECT, "Blind Transfer", "blindxfer", "#", "#", builtin_blindtransfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
{ AST_FEATURE_REDIRECT, "Attended Transfer", "atxfer", "", "", builtin_atxfer, AST_FEATURE_FLAG_NEEDSDTMF, "" },
{ AST_FEATURE_AUTOMON, "One Touch Monitor", "automon", "", "", builtin_automonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
{ AST_FEATURE_DISCONNECT, "Disconnect Call", "disconnect", "*", "*", builtin_disconnect, AST_FEATURE_FLAG_NEEDSDTMF, "" },
{ AST_FEATURE_PARKCALL, "Park Call", "parkcall", "", "", builtin_parkcall, AST_FEATURE_FLAG_NEEDSDTMF, "" },
{ AST_FEATURE_AUTOMIXMON, "One Touch MixMonitor", "automixmon", "", "", builtin_automixmonitor, AST_FEATURE_FLAG_NEEDSDTMF, "" },
};
static AST_RWLIST_HEAD_STATIC(feature_list, ast_call_feature);
/*! \brief register new feature into feature_list*/
void ast_register_feature(struct ast_call_feature *feature)
{
if (!feature) {
ast_log(LOG_NOTICE,"You didn't pass a feature!\n");
return;
}
AST_RWLIST_WRLOCK(&feature_list);
AST_RWLIST_INSERT_HEAD(&feature_list,feature,feature_entry);
AST_RWLIST_UNLOCK(&feature_list);
ast_verb(2, "Registered Feature '%s'\n",feature->sname);
}
/*!
* \brief Add new feature group
* \param fgname feature group name.
*
* Add new feature group to the feature group list insert at head of list.
* \note This function MUST be called while feature_groups is locked.
*/
static struct feature_group* register_group(const char *fgname)
{
struct feature_group *fg;
if (!fgname) {
ast_log(LOG_NOTICE, "You didn't pass a new group name!\n");
return NULL;
}
if (!(fg = ast_calloc(1, sizeof(*fg))))
return NULL;
if (ast_string_field_init(fg, 128)) {
ast_free(fg);
return NULL;
}
ast_string_field_set(fg, gname, fgname);
AST_LIST_INSERT_HEAD(&feature_groups, fg, entry);
ast_verb(2, "Registered group '%s'\n", fg->gname);
return fg;
}
/*!
* \brief Add feature to group
* \param fg feature group
* \param exten
* \param feature feature to add.
*
* Check fg and feature specified, add feature to list
* \note This function MUST be called while feature_groups is locked.
*/
static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
{
struct feature_group_exten *fge;
if (!fg) {
ast_log(LOG_NOTICE, "You didn't pass a group!\n");
return;
}
if (!feature) {
ast_log(LOG_NOTICE, "You didn't pass a feature!\n");
return;
}
if (!(fge = ast_calloc(1, sizeof(*fge))))
return;
if (ast_string_field_init(fge, 128)) {
ast_free(fge);
return;
}
ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
fge->feature = feature;
AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
feature->sname, fg->gname, exten);
}
void ast_unregister_feature(struct ast_call_feature *feature)
{
if (!feature) {
return;
}
AST_RWLIST_WRLOCK(&feature_list);
AST_RWLIST_REMOVE(&feature_list, feature, feature_entry);
AST_RWLIST_UNLOCK(&feature_list);
ast_free(feature);
}
/*! \brief Remove all features in the list */
static void ast_unregister_features(void)
{
struct ast_call_feature *feature;
AST_RWLIST_WRLOCK(&feature_list);
while ((feature = AST_RWLIST_REMOVE_HEAD(&feature_list, feature_entry))) {
ast_free(feature);
}
AST_RWLIST_UNLOCK(&feature_list);
}
/*! \brief find a call feature by name */
static struct ast_call_feature *find_dynamic_feature(const char *name)
{
struct ast_call_feature *tmp;
AST_RWLIST_TRAVERSE(&feature_list, tmp, feature_entry) {
if (!strcasecmp(tmp->sname, name)) {
break;
}
}
return tmp;
}
/*! \brief Remove all feature groups in the list */
static void ast_unregister_groups(void)
{
struct feature_group *fg;
struct feature_group_exten *fge;
AST_RWLIST_WRLOCK(&feature_groups);
while ((fg = AST_LIST_REMOVE_HEAD(&feature_groups, entry))) {
while ((fge = AST_LIST_REMOVE_HEAD(&fg->features, entry))) {
ast_string_field_free_memory(fge);
ast_free(fge);
}
ast_string_field_free_memory(fg);
ast_free(fg);
}
AST_RWLIST_UNLOCK(&feature_groups);
}
/*!
* \brief Find a group by name
* \param name feature name
* \retval feature group on success.
* \retval NULL on failure.
*/
static struct feature_group *find_group(const char *name) {
struct feature_group *fg = NULL;
AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
if (!strcasecmp(fg->gname, name))
break;
}
return fg;
}
void ast_rdlock_call_features(void)
{
ast_rwlock_rdlock(&features_lock);
}
void ast_unlock_call_features(void)
{
ast_rwlock_unlock(&features_lock);
}
struct ast_call_feature *ast_find_call_feature(const char *name)
{
int x;
for (x = 0; x < FEATURES_COUNT; x++) {
if (!strcasecmp(name, builtin_features[x].sname))
return &builtin_features[x];
}
return NULL;
}
/*!
* \brief exec an app by feature
* \param chan,peer,config,code,sense,data
*
* Find a feature, determine which channel activated
* \retval -1 error.
* \retval -2 when an application cannot be found.
*/
static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data)
{
struct ast_app *app;
struct ast_call_feature *feature = data;
struct ast_channel *work, *idle;
int res;
if (!feature) { /* shouldn't ever happen! */
ast_log(LOG_NOTICE, "Found feature before, but at execing we've lost it??\n");
return -1;
}
if (sense == FEATURE_SENSE_CHAN) {
if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
return FEATURE_RETURN_KEEPTRYING;
if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
work = chan;
idle = peer;
} else {
work = peer;
idle = chan;
}
} else {
if (!ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
return FEATURE_RETURN_KEEPTRYING;
if (ast_test_flag(feature, AST_FEATURE_FLAG_ONSELF)) {
work = peer;
idle = chan;
} else {
work = chan;
idle = peer;
}
}
if (!(app = pbx_findapp(feature->app))) {
ast_log(LOG_WARNING, "Could not find application (%s)\n", feature->app);
return -2;
}
ast_autoservice_start(idle);
if (!ast_strlen_zero(feature->moh_class))
ast_moh_start(idle, feature->moh_class, NULL);
res = pbx_exec(work, app, feature->app_args);
if (!ast_strlen_zero(feature->moh_class))
ast_moh_stop(idle);
ast_autoservice_stop(idle);
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
if (res) {
return FEATURE_RETURN_SUCCESSBREAK;
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
}
return FEATURE_RETURN_SUCCESS; /*! \todo XXX should probably return res */
}
static void unmap_features(void)
{
int x;
ast_rwlock_wrlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++)
strcpy(builtin_features[x].exten, builtin_features[x].default_exten);
ast_rwlock_unlock(&features_lock);
}
static int remap_feature(const char *name, const char *value)
{
int x, res = -1;
ast_rwlock_wrlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++) {
if (strcasecmp(builtin_features[x].sname, name))
continue;
ast_copy_string(builtin_features[x].exten, value, sizeof(builtin_features[x].exten));
res = 0;
break;
}
ast_rwlock_unlock(&features_lock);
return res;
}
/*!
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
* \brief Helper function for feature_interpret and ast_feature_detect
* \param chan,peer,config,code,sense,dynamic_features char buf,feature flags,operation,feature
*
* Lock features list, browse for code, unlock list
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
* If a feature is found and the operation variable is set, that feature's
* operation is executed. The first feature found is copied to the feature parameter.
* \retval res on success.
* \retval -1 on failure.
*/
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel *peer,
struct ast_bridge_config *config, char *code, int sense, char *dynamic_features_buf,
struct ast_flags *features, int operation, struct ast_call_feature *feature)
{
int x;
struct feature_group *fg = NULL;
struct feature_group_exten *fge;
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
struct ast_call_feature *tmpfeature;
char *tmp, *tok;
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
int res = AST_FEATURE_RETURN_PASSDIGITS;
int feature_detected = 0;
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if (!(peer && chan && config) && operation) {
return -1; /* can not run feature operation */
}
Merged revisions 182029 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r182029 | mmichelson | 2009-03-13 12:26:43 -0500 (Fri, 13 Mar 2009) | 41 lines Merged revisions 181990 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r181990 | mmichelson | 2009-03-13 12:12:32 -0500 (Fri, 13 Mar 2009) | 35 lines Check the DYNAMIC_FEATURES of both the chan and peer when interpreting DTMF. Dynamic features defined in the applicationmap section of features.conf allow one to specify whether the caller, callee, or both have the ability to use the feature. The documentation in the features.conf.sample file could be interpreted to mean that one only needs to set the DYNAMIC_FEATURES channel variable on the calling channel in order to allow for the callee to be able to use the features which he should have permission to use. However, the DYNAMIC_FEATURES variable would only be read from the channel of the participant that pressed the DTMF sequence to activate the feature. The result of this was that the callee was unable to use dynamic features unless the dialplan writer had taken measures to be sure that the DYNAMIC_FEATURES variable was set on the callee's channel. This commit changes the behavior of ast_feature_interpret to concatenate the values of DYNAMIC_FEATURES from both parties involved in the bridge. The features themselves determine who has permission to use them, so there is no reason to believe that one side of the bridge could gain the ability to perform an action that they should not have the ability to perform. Kevin Fleming pointed out on the asterisk-users list that the typical way that this was worked around in the past was by setting _DYNAMIC_FEATURES on the calling channel so that the value would be inherited by the called channel. While this works, the documentation alone is not enough to figure out why this is necessary for the callee to be able to use dynamic features. In this particular case, changing the code to match the documentation is safe, easy, and will generally make things easier for people for future installations. This bug was originally reported on the asterisk-users list by David Ruggles. (closes issue #14657) Reported by: mmichelson Patches: 14657.patch uploaded by mmichelson (license 60) ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@182064 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-13 17:33:29 +00:00
ast_rwlock_rdlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++) {
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
!ast_strlen_zero(builtin_features[x].exten)) {
/* Feature is up for consideration */
if (!strcmp(builtin_features[x].exten, code)) {
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
ast_debug(3, "Feature detected: fname=%s sname=%s exten=%s\n", builtin_features[x].fname, builtin_features[x].sname, builtin_features[x].exten);
if (operation) {
res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
}
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
memcpy(feature, &builtin_features[x], sizeof(feature));
feature_detected = 1;
break;
} else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if (res == AST_FEATURE_RETURN_PASSDIGITS)
res = AST_FEATURE_RETURN_STOREDIGITS;
}
}
}
ast_rwlock_unlock(&features_lock);
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if (ast_strlen_zero(dynamic_features_buf) || feature_detected) {
return res;
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
}
Merged revisions 182029 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r182029 | mmichelson | 2009-03-13 12:26:43 -0500 (Fri, 13 Mar 2009) | 41 lines Merged revisions 181990 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r181990 | mmichelson | 2009-03-13 12:12:32 -0500 (Fri, 13 Mar 2009) | 35 lines Check the DYNAMIC_FEATURES of both the chan and peer when interpreting DTMF. Dynamic features defined in the applicationmap section of features.conf allow one to specify whether the caller, callee, or both have the ability to use the feature. The documentation in the features.conf.sample file could be interpreted to mean that one only needs to set the DYNAMIC_FEATURES channel variable on the calling channel in order to allow for the callee to be able to use the features which he should have permission to use. However, the DYNAMIC_FEATURES variable would only be read from the channel of the participant that pressed the DTMF sequence to activate the feature. The result of this was that the callee was unable to use dynamic features unless the dialplan writer had taken measures to be sure that the DYNAMIC_FEATURES variable was set on the callee's channel. This commit changes the behavior of ast_feature_interpret to concatenate the values of DYNAMIC_FEATURES from both parties involved in the bridge. The features themselves determine who has permission to use them, so there is no reason to believe that one side of the bridge could gain the ability to perform an action that they should not have the ability to perform. Kevin Fleming pointed out on the asterisk-users list that the typical way that this was worked around in the past was by setting _DYNAMIC_FEATURES on the calling channel so that the value would be inherited by the called channel. While this works, the documentation alone is not enough to figure out why this is necessary for the callee to be able to use dynamic features. In this particular case, changing the code to match the documentation is safe, easy, and will generally make things easier for people for future installations. This bug was originally reported on the asterisk-users list by David Ruggles. (closes issue #14657) Reported by: mmichelson Patches: 14657.patch uploaded by mmichelson (license 60) ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@182064 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-13 17:33:29 +00:00
tmp = dynamic_features_buf;
while ((tok = strsep(&tmp, "#"))) {
AST_RWLIST_RDLOCK(&feature_groups);
fg = find_group(tok);
if (fg) {
AST_LIST_TRAVERSE(&fg->features, fge, entry) {
if (strcasecmp(fge->exten, code))
continue;
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if (operation) {
res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
}
memcpy(feature, fge->feature, sizeof(feature));
if (res != AST_FEATURE_RETURN_KEEPTRYING) {
AST_RWLIST_UNLOCK(&feature_groups);
break;
}
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
res = AST_FEATURE_RETURN_PASSDIGITS;
}
if (fge)
break;
}
AST_RWLIST_UNLOCK(&feature_groups);
AST_RWLIST_RDLOCK(&feature_list);
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if (!(tmpfeature = find_dynamic_feature(tok))) {
AST_RWLIST_UNLOCK(&feature_list);
continue;
}
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
/* Feature is up for consideration */
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
if (!strcmp(tmpfeature->exten, code)) {
ast_verb(3, " Feature Found: %s exten: %s\n",tmpfeature->sname, tok);
if (operation) {
res = tmpfeature->operation(chan, peer, config, code, sense, tmpfeature);
}
memcpy(feature, tmpfeature, sizeof(feature));
if (res != AST_FEATURE_RETURN_KEEPTRYING) {
AST_RWLIST_UNLOCK(&feature_list);
break;
}
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
res = AST_FEATURE_RETURN_PASSDIGITS;
} else if (!strncmp(tmpfeature->exten, code, strlen(code)))
res = AST_FEATURE_RETURN_STOREDIGITS;
AST_RWLIST_UNLOCK(&feature_list);
}
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
return res;
}
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
/*!
* \brief Check the dynamic features
* \param chan,peer,config,code,sense
*
* \retval res on success.
* \retval -1 on failure.
*/
static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense) {
char dynamic_features_buf[128];
const char *peer_dynamic_features, *chan_dynamic_features;
struct ast_flags features;
struct ast_call_feature feature;
if (sense == FEATURE_SENSE_CHAN) {
ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
}
else {
ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
}
ast_channel_lock(peer);
peer_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES"),""));
ast_channel_unlock(peer);
ast_channel_lock(chan);
chan_dynamic_features = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"),""));
ast_channel_unlock(chan);
snprintf(dynamic_features_buf, sizeof(dynamic_features_buf), "%s%s%s", S_OR(chan_dynamic_features, ""), chan_dynamic_features && peer_dynamic_features ? "#" : "", S_OR(peer_dynamic_features,""));
ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features_buf);
return feature_interpret_helper(chan, peer, config, code, sense, dynamic_features_buf, &features, 1, &feature);
}
int ast_feature_detect(struct ast_channel *chan, struct ast_flags *features, char *code, struct ast_call_feature *feature) {
return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, 0, feature);
Merged revisions 183172 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r183172 | dvossel | 2009-03-19 11:28:33 -0500 (Thu, 19 Mar 2009) | 20 lines Merged revisions 183126 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r183126 | dvossel | 2009-03-19 11:15:16 -0500 (Thu, 19 Mar 2009) | 17 lines Allow disconnect feature before a call is bridged feature.conf has a disconnect option. By default this option is set to '*', but it could be anything. If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else. This is because features are unavailable until bridging takes place. The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different. This patch allows features to be detected from outside of the bridge, but not operated on. In this case, the disconnect feature can be detected before briding and handled outside of features.c. (closes issue #11583) Reported by: sobomax Patches: patch-apps__app_dial.c uploaded by sobomax (license 359) 11583.latest-patch uploaded by murf (license 17) detect_disconnect.diff uploaded by dvossel (license 671) Tested by: sobomax, dvossel Review: http://reviewboard.digium.com/r/195/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@183199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-19 17:10:09 +00:00
}
static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config)
{
int x;
ast_clear_flag(config, AST_FLAGS_ALL);
ast_rwlock_rdlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++) {
if (!ast_test_flag(builtin_features + x, AST_FEATURE_FLAG_NEEDSDTMF))
continue;
if (ast_test_flag(&(config->features_caller), builtin_features[x].feature_mask))
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
if (ast_test_flag(&(config->features_callee), builtin_features[x].feature_mask))
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
}
ast_rwlock_unlock(&features_lock);
if (chan && peer && !(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
if (dynamic_features) {
char *tmp = ast_strdupa(dynamic_features);
char *tok;
struct ast_call_feature *feature;
/* while we have a feature */
while ((tok = strsep(&tmp, "#"))) {
AST_RWLIST_RDLOCK(&feature_list);
if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
}
AST_RWLIST_UNLOCK(&feature_list);
}
}
}
}
/*!
* \brief Get feature and dial
* \param caller,transferee,type,format,data,timeout,outstate,cid_num,cid_name,igncallerstate
*
* Request channel, set channel variables, initiate call,check if they want to disconnect
* go into loop, check if timeout has elapsed, check if person to be transfered hung up,
* check for answer break loop, set cdr return channel.
*
* \todo XXX Check - this is very similar to the code in channel.c
* \return always a channel
*/
static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *caller, struct ast_channel *transferee, const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, int igncallerstate, const char *language)
{
int state = 0;
int cause = 0;
int to;
struct ast_channel *chan;
struct ast_channel *monitor_chans[2];
struct ast_channel *active_channel;
int res = 0, ready = 0;
if ((chan = ast_request(type, format, data, &cause))) {
ast_set_callerid(chan, cid_num, cid_name, cid_num);
ast_string_field_set(chan, language, language);
ast_channel_inherit_variables(caller, chan);
pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
if (!ast_call(chan, data, timeout)) {
struct timeval started;
int x, len = 0;
char *disconnect_code = NULL, *dialed_code = NULL;
ast_indicate(caller, AST_CONTROL_RINGING);
/* support dialing of the featuremap disconnect code while performing an attended tranfer */
ast_rwlock_rdlock(&features_lock);
for (x = 0; x < FEATURES_COUNT; x++) {
if (strcasecmp(builtin_features[x].sname, "disconnect"))
continue;
disconnect_code = builtin_features[x].exten;
len = strlen(disconnect_code) + 1;
dialed_code = alloca(len);
memset(dialed_code, 0, len);
break;
}
ast_rwlock_unlock(&features_lock);
x = 0;
started = ast_tvnow();
to = timeout;
ast_poll_channel_add(caller, chan);
while (!((transferee && ast_check_hangup(transferee)) && (!igncallerstate && ast_check_hangup(caller))) && timeout && (chan->_state != AST_STATE_UP)) {
struct ast_frame *f = NULL;
monitor_chans[0] = caller;
monitor_chans[1] = chan;
active_channel = ast_waitfor_n(monitor_chans, 2, &to);
/* see if the timeout has been violated */
if(ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
state = AST_CONTROL_UNHOLD;
ast_log(LOG_NOTICE, "We exceeded our AT-timeout\n");
break; /*doh! timeout*/
}
if (!active_channel)
continue;
if (chan && (chan == active_channel)) {
if (!ast_strlen_zero(chan->call_forward)) {
if (!(chan = ast_call_forward(caller, chan, &to, format, NULL, outstate))) {
return NULL;
}
continue;
}
f = ast_read(chan);
if (f == NULL) { /*doh! where'd he go?*/
state = AST_CONTROL_HANGUP;
res = 0;
break;
}
if (f->frametype == AST_FRAME_CONTROL || f->frametype == AST_FRAME_DTMF || f->frametype == AST_FRAME_TEXT) {
if (f->subclass == AST_CONTROL_RINGING) {
state = f->subclass;
ast_verb(3, "%s is ringing\n", chan->name);
ast_indicate(caller, AST_CONTROL_RINGING);
} else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
state = f->subclass;
ast_verb(3, "%s is busy\n", chan->name);
ast_indicate(caller, AST_CONTROL_BUSY);
ast_frfree(f);
f = NULL;
break;
} else if (f->subclass == AST_CONTROL_ANSWER) {
/* This is what we are hoping for */
state = f->subclass;
ast_frfree(f);
f = NULL;
ready=1;
break;
} else if (f->subclass != -1) {
ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
}
/* else who cares */
}
} else if (caller && (active_channel == caller)) {
f = ast_read(caller);
if (f == NULL) { /*doh! where'd he go?*/
if (!igncallerstate) {
if (ast_check_hangup(caller) && !ast_check_hangup(chan)) {
/* make this a blind transfer */
ready = 1;
break;
}
state = AST_CONTROL_HANGUP;
res = 0;
break;
}
} else {
if (f->frametype == AST_FRAME_DTMF) {
dialed_code[x++] = f->subclass;
dialed_code[x] = '\0';
if (strlen(dialed_code) == len) {
x = 0;
} else if (x && strncmp(dialed_code, disconnect_code, x)) {
x = 0;
dialed_code[x] = '\0';
}
if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
/* Caller Canceled the call */
state = AST_CONTROL_UNHOLD;
ast_frfree(f);
f = NULL;
break;
}
}
}
}
if (f)
ast_frfree(f);
} /* end while */
ast_poll_channel_del(caller, chan);
} else
ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
} else {
ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, (char *)data);
switch(cause) {
case AST_CAUSE_BUSY:
state = AST_CONTROL_BUSY;
break;
case AST_CAUSE_CONGESTION:
state = AST_CONTROL_CONGESTION;
break;
}
}
ast_indicate(caller, -1);
if (chan && ready) {
if (chan->_state == AST_STATE_UP)
state = AST_CONTROL_ANSWER;
res = 0;
} else if(chan) {
res = -1;
ast_hangup(chan);
chan = NULL;
} else {
res = -1;
}
if (outstate)
*outstate = state;
return chan;
}
/*!
* \brief return the first unlocked cdr in a possible chain
*/
static struct ast_cdr *pick_unlocked_cdr(struct ast_cdr *cdr)
{
struct ast_cdr *cdr_orig = cdr;
while (cdr) {
if (!ast_test_flag(cdr,AST_CDR_FLAG_LOCKED))
return cdr;
cdr = cdr->next;
}
return cdr_orig; /* everybody LOCKED or some other weirdness, like a NULL */
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
{
const char *feature;
if (ast_strlen_zero(features)) {
return;
}
for (feature = features; *feature; feature++) {
switch (*feature) {
case 'T' :
case 't' :
ast_set_flag(&(config->features_caller), AST_FEATURE_REDIRECT);
break;
case 'K' :
case 'k' :
ast_set_flag(&(config->features_caller), AST_FEATURE_PARKCALL);
break;
case 'H' :
case 'h' :
ast_set_flag(&(config->features_caller), AST_FEATURE_DISCONNECT);
break;
case 'W' :
case 'w' :
ast_set_flag(&(config->features_caller), AST_FEATURE_AUTOMON);
break;
default :
ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
}
}
}
static void add_features_datastores(struct ast_channel *caller, struct ast_channel *callee, struct ast_bridge_config *config)
{
struct ast_datastore *ds_callee_features = NULL, *ds_caller_features = NULL;
struct ast_dial_features *callee_features = NULL, *caller_features = NULL;
ast_channel_lock(caller);
ds_caller_features = ast_channel_datastore_find(caller, &dial_features_info, NULL);
ast_channel_unlock(caller);
if (!ds_caller_features) {
if (!(ds_caller_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) {
ast_log(LOG_WARNING, "Unable to create channel datastore for caller features. Aborting!\n");
return;
}
if (!(caller_features = ast_calloc(1, sizeof(*caller_features)))) {
ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
ast_channel_datastore_free(ds_caller_features);
return;
}
ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
caller_features->is_caller = 1;
ast_copy_flags(&(caller_features->features_callee), &(config->features_callee), AST_FLAGS_ALL);
ast_copy_flags(&(caller_features->features_caller), &(config->features_caller), AST_FLAGS_ALL);
ds_caller_features->data = caller_features;
ast_channel_lock(caller);
ast_channel_datastore_add(caller, ds_caller_features);
ast_channel_unlock(caller);
} else {
/* If we don't return here, then when we do a builtin_atxfer we will copy the disconnect
* flags over from the atxfer to the caller */
return;
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
}
ast_channel_lock(callee);
ds_callee_features = ast_channel_datastore_find(callee, &dial_features_info, NULL);
ast_channel_unlock(callee);
if (!ds_callee_features) {
if (!(ds_callee_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) {
ast_log(LOG_WARNING, "Unable to create channel datastore for callee features. Aborting!\n");
return;
}
if (!(callee_features = ast_calloc(1, sizeof(*callee_features)))) {
ast_log(LOG_WARNING, "Unable to allocate memory for callee feature flags. Aborting!\n");
ast_channel_datastore_free(ds_callee_features);
return;
}
ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
callee_features->is_caller = 0;
ast_copy_flags(&(callee_features->features_callee), &(config->features_caller), AST_FLAGS_ALL);
ast_copy_flags(&(callee_features->features_caller), &(config->features_callee), AST_FLAGS_ALL);
ds_callee_features->data = callee_features;
ast_channel_lock(callee);
ast_channel_datastore_add(callee, ds_callee_features);
ast_channel_unlock(callee);
}
return;
}
/*!
* \brief bridge the call and set CDR
* \param chan,peer,config
*
* Set start time, check for two channels,check if monitor on
* check for feature activation, create new CDR
* \retval res on success.
* \retval -1 on failure to bridge.
*/
int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast_bridge_config *config)
{
/* Copy voice back and forth between the two channels. Give the peer
the ability to transfer calls with '#<extension' syntax. */
struct ast_frame *f;
struct ast_channel *who;
char chan_featurecode[FEATURE_MAX_LEN + 1]="";
char peer_featurecode[FEATURE_MAX_LEN + 1]="";
char orig_channame[AST_MAX_EXTENSION];
char orig_peername[AST_MAX_EXTENSION];
int res;
int diff;
int hasfeatures=0;
int hadfeatures=0;
int autoloopflag;
struct ast_option_header *aoh;
struct ast_bridge_config backup_config;
struct ast_cdr *bridge_cdr = NULL;
Merged revisions 134922 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r134922 | murf | 2008-07-31 13:48:08 -0600 (Thu, 31 Jul 2008) | 63 lines Merged revisions 134883 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r134883 | murf | 2008-07-31 13:23:42 -0600 (Thu, 31 Jul 2008) | 51 lines (closes issue #11849) Reported by: greyvoip Tested by: murf OK, a few days of debugging, a bunch of instrumentation in chan_sip, main/channel.c, main/pbx.c, etc. and 5 solid notebook pages of notes later, I have made the small tweek necc. to get the start time right on the second CDR when: A Calls B B answ. A hits Xfer button on sip phone, A dials C and hits the OK button, A hangs up C answers ringing phone B and C converse B and/or C hangs up But does not harm the scenario where: A Calls B B answ. B hits xfer button on sip phone, B dials C and hits the OK button, B hangs up C answers ringing phone A and C converse A and/or C hangs up The difference in start times on the second CDR is because of a Masquerade on the B channel when the xfer number is sent. It ends up replacing the CDR on the B channel with a duplicate, which ends up getting tossed out. We keep a pointer to the first CDR, and update *that* after the bridge closes. But, only if the CDR has changed. I hope this change is specific enough not to muck up any current CDR-based apps. In my defence, I assert that the previous information was wrong, and this change fixes it, and possibly other similar scenarios. I wonder if I should be doing the same thing for the channel, as I did for the peer, but I can't think of a scenario this might affect. I leave it, then, as an exersize for the users, to find the scenario where the chan's CDR changes and loses the proper start time. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@134923 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-07-31 19:54:58 +00:00
struct ast_cdr *orig_peer_cdr = NULL;
struct ast_cdr *chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
struct ast_cdr *peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */
memset(&backup_config, 0, sizeof(backup_config));
config->start_time = ast_tvnow();
if (chan && peer) {
pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name);
pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name);
Merged revisions 164203 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r164203 | russell | 2008-12-15 08:40:24 -0600 (Mon, 15 Dec 2008) | 39 lines Merged revisions 164201 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r164201 | russell | 2008-12-15 08:31:37 -0600 (Mon, 15 Dec 2008) | 31 lines Handle a case where a call can be bridged to a channel that is still ringing. The issue that was reported was about a case where a RINGING channel got redirected to an extension to pick up a call from parking. Once the parked call got taken out of parking, it heard silence until the other side answered. Ideally, the caller that was parked would get a ringing indication. This patch fixes this case so that the caller receives ringback once it comes out of parking until the other side answers. The fixes are: - Make sure we remember that a channel was an outgoing channel when doing a masquerade. This prevents an erroneous ast_answer() call on the channel, which causes a bogus 200 OK to be sent in the case of SIP. - Add some additional comments to explain related parts of code. - Update the handling of the ast_channel visible_indication field. Storing values that are not stateful is pointless. Control frames that are events or commands should be ignored. - When a bridge first starts, check to see if the peer channel needs to be given ringing indication because the calling side is still ringing. - Rework ast_indicate_data() a bit for the sake of readability. (closes issue #13747) Reported by: davidw Tested by: russell Review: http://reviewboard.digium.com/r/90/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@164279 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-15 16:26:09 +00:00
} else if (chan) {
pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL);
Merged revisions 164203 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r164203 | russell | 2008-12-15 08:40:24 -0600 (Mon, 15 Dec 2008) | 39 lines Merged revisions 164201 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r164201 | russell | 2008-12-15 08:31:37 -0600 (Mon, 15 Dec 2008) | 31 lines Handle a case where a call can be bridged to a channel that is still ringing. The issue that was reported was about a case where a RINGING channel got redirected to an extension to pick up a call from parking. Once the parked call got taken out of parking, it heard silence until the other side answered. Ideally, the caller that was parked would get a ringing indication. This patch fixes this case so that the caller receives ringback once it comes out of parking until the other side answers. The fixes are: - Make sure we remember that a channel was an outgoing channel when doing a masquerade. This prevents an erroneous ast_answer() call on the channel, which causes a bogus 200 OK to be sent in the case of SIP. - Add some additional comments to explain related parts of code. - Update the handling of the ast_channel visible_indication field. Storing values that are not stateful is pointless. Control frames that are events or commands should be ignored. - When a bridge first starts, check to see if the peer channel needs to be given ringing indication because the calling side is still ringing. - Rework ast_indicate_data() a bit for the sake of readability. (closes issue #13747) Reported by: davidw Tested by: russell Review: http://reviewboard.digium.com/r/90/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@164279 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-15 16:26:09 +00:00
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
add_features_datastores(chan, peer, config);
Merged revisions 164203 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r164203 | russell | 2008-12-15 08:40:24 -0600 (Mon, 15 Dec 2008) | 39 lines Merged revisions 164201 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r164201 | russell | 2008-12-15 08:31:37 -0600 (Mon, 15 Dec 2008) | 31 lines Handle a case where a call can be bridged to a channel that is still ringing. The issue that was reported was about a case where a RINGING channel got redirected to an extension to pick up a call from parking. Once the parked call got taken out of parking, it heard silence until the other side answered. Ideally, the caller that was parked would get a ringing indication. This patch fixes this case so that the caller receives ringback once it comes out of parking until the other side answers. The fixes are: - Make sure we remember that a channel was an outgoing channel when doing a masquerade. This prevents an erroneous ast_answer() call on the channel, which causes a bogus 200 OK to be sent in the case of SIP. - Add some additional comments to explain related parts of code. - Update the handling of the ast_channel visible_indication field. Storing values that are not stateful is pointless. Control frames that are events or commands should be ignored. - When a bridge first starts, check to see if the peer channel needs to be given ringing indication because the calling side is still ringing. - Rework ast_indicate_data() a bit for the sake of readability. (closes issue #13747) Reported by: davidw Tested by: russell Review: http://reviewboard.digium.com/r/90/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@164279 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-15 16:26:09 +00:00
/* This is an interesting case. One example is if a ringing channel gets redirected to
* an extension that picks up a parked call. This will make sure that the call taken
* out of parking gets told that the channel it just got bridged to is still ringing. */
if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) {
ast_indicate(peer, AST_CONTROL_RINGING);
}
if (monitor_ok) {
const char *monitor_exec;
struct ast_channel *src = NULL;
if (!monitor_app) {
if (!(monitor_app = pbx_findapp("Monitor")))
monitor_ok=0;
}
if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR")))
src = chan;
else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR")))
src = peer;
if (monitor_app && src) {
char *tmp = ast_strdupa(monitor_exec);
pbx_exec(src, monitor_app, tmp);
}
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
set_config_flags(chan, peer, config);
config->firstpass = 1;
/* Answer if need be */
if (chan->_state != AST_STATE_UP) {
if (ast_raw_answer(chan, 1)) {
return -1;
}
}
ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
orig_peer_cdr = peer_cdr;
if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) {
if (chan_cdr) {
ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN);
ast_cdr_update(chan);
bridge_cdr = ast_cdr_dup(chan_cdr);
ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
} else {
/* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp));
ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata));
ast_cdr_setcid(bridge_cdr, chan);
bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL;
bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags;
ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
/* Destination information */
ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
if (peer_cdr) {
bridge_cdr->start = peer_cdr->start;
ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield));
} else {
ast_cdr_start(bridge_cdr);
}
}
ast_debug(4,"bridge answer set, chan answer set\n");
/* peer_cdr->answer will be set when a macro runs on the peer;
Merged revisions 135821 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r135821 | murf | 2008-08-05 17:45:32 -0600 (Tue, 05 Aug 2008) | 42 lines Merged revisions 135799 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r135799 | murf | 2008-08-05 17:13:20 -0600 (Tue, 05 Aug 2008) | 34 lines (closes issue #12982) Reported by: bcnit Tested by: murf I discovered that also, in the previous bug fixes and changes, the cdr.conf 'unanswered' option is not being obeyed, so I fixed this. And, yes, there are two 'answer' times involved in this scenario, and I would agree with you, that the first answer time is the time that should appear in the CDR. (the second 'answer' time is the time that the bridge was begun). I made the necessary adjustments, recording the first answer time into the peer cdr, and then using that to override the bridge cdr's value. To get the 'unanswered' CDRs to appear, I purposely output them, using the dial cmd to mark them as DIALED (with a new flag), and outputting them if they bear that flag, and you are in the right mode. I also corrected one small mention of the Zap device to equally consider the dahdi device. I heavily tested 10-sec-wait macros in dial, and without the macro call; I tested hangups while the macro was running vs. letting the macro complete and the bridge form. Looks OK. Removed all the instrumentation and debug. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@135822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-08-05 23:52:14 +00:00
in that case, the bridge answer will be delayed while the
macro plays on the peer channel. The peer answered the call
before the macro started playing. To the phone system,
this is billable time for the call, even tho the caller
hears nothing but ringing while the macro does its thing. */
/* Another case where the peer cdr's time will be set, is when
A self-parks by pickup up phone and dialing 700, then B
picks up A by dialing its parking slot; there may be more
practical paths that get the same result, tho... in which
case you get the previous answer time from the Park... which
is before the bridge's start time, so I added in the
tvcmp check to the if below */
if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer->cdr->answer, bridge_cdr->start) >= 0) {
bridge_cdr->answer = peer_cdr->answer;
bridge_cdr->disposition = peer_cdr->disposition;
if (chan_cdr) {
chan_cdr->answer = peer_cdr->answer;
chan_cdr->disposition = peer_cdr->disposition;
}
Merged revisions 135821 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r135821 | murf | 2008-08-05 17:45:32 -0600 (Tue, 05 Aug 2008) | 42 lines Merged revisions 135799 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r135799 | murf | 2008-08-05 17:13:20 -0600 (Tue, 05 Aug 2008) | 34 lines (closes issue #12982) Reported by: bcnit Tested by: murf I discovered that also, in the previous bug fixes and changes, the cdr.conf 'unanswered' option is not being obeyed, so I fixed this. And, yes, there are two 'answer' times involved in this scenario, and I would agree with you, that the first answer time is the time that should appear in the CDR. (the second 'answer' time is the time that the bridge was begun). I made the necessary adjustments, recording the first answer time into the peer cdr, and then using that to override the bridge cdr's value. To get the 'unanswered' CDRs to appear, I purposely output them, using the dial cmd to mark them as DIALED (with a new flag), and outputting them if they bear that flag, and you are in the right mode. I also corrected one small mention of the Zap device to equally consider the dahdi device. I heavily tested 10-sec-wait macros in dial, and without the macro call; I tested hangups while the macro was running vs. letting the macro complete and the bridge form. Looks OK. Removed all the instrumentation and debug. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@135822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-08-05 23:52:14 +00:00
} else {
ast_cdr_answer(bridge_cdr);
if (chan_cdr) {
ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */
}
Merged revisions 135821 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r135821 | murf | 2008-08-05 17:45:32 -0600 (Tue, 05 Aug 2008) | 42 lines Merged revisions 135799 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r135799 | murf | 2008-08-05 17:13:20 -0600 (Tue, 05 Aug 2008) | 34 lines (closes issue #12982) Reported by: bcnit Tested by: murf I discovered that also, in the previous bug fixes and changes, the cdr.conf 'unanswered' option is not being obeyed, so I fixed this. And, yes, there are two 'answer' times involved in this scenario, and I would agree with you, that the first answer time is the time that should appear in the CDR. (the second 'answer' time is the time that the bridge was begun). I made the necessary adjustments, recording the first answer time into the peer cdr, and then using that to override the bridge cdr's value. To get the 'unanswered' CDRs to appear, I purposely output them, using the dial cmd to mark them as DIALED (with a new flag), and outputting them if they bear that flag, and you are in the right mode. I also corrected one small mention of the Zap device to equally consider the dahdi device. I heavily tested 10-sec-wait macros in dial, and without the macro call; I tested hangups while the macro was running vs. letting the macro complete and the bridge form. Looks OK. Removed all the instrumentation and debug. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@135822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-08-05 23:52:14 +00:00
}
if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) {
if (chan_cdr) {
ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED);
}
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
if (peer_cdr) {
ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED);
}
Merged revisions 134922 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r134922 | murf | 2008-07-31 13:48:08 -0600 (Thu, 31 Jul 2008) | 63 lines Merged revisions 134883 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r134883 | murf | 2008-07-31 13:23:42 -0600 (Thu, 31 Jul 2008) | 51 lines (closes issue #11849) Reported by: greyvoip Tested by: murf OK, a few days of debugging, a bunch of instrumentation in chan_sip, main/channel.c, main/pbx.c, etc. and 5 solid notebook pages of notes later, I have made the small tweek necc. to get the start time right on the second CDR when: A Calls B B answ. A hits Xfer button on sip phone, A dials C and hits the OK button, A hangs up C answers ringing phone B and C converse B and/or C hangs up But does not harm the scenario where: A Calls B B answ. B hits xfer button on sip phone, B dials C and hits the OK button, B hangs up C answers ringing phone A and C converse A and/or C hangs up The difference in start times on the second CDR is because of a Masquerade on the B channel when the xfer number is sent. It ends up replacing the CDR on the B channel with a duplicate, which ends up getting tossed out. We keep a pointer to the first CDR, and update *that* after the bridge closes. But, only if the CDR has changed. I hope this change is specific enough not to muck up any current CDR-based apps. In my defence, I assert that the previous information was wrong, and this change fixes it, and possibly other similar scenarios. I wonder if I should be doing the same thing for the channel, as I did for the peer, but I can't think of a scenario this might affect. I leave it, then, as an exersize for the users, to find the scenario where the chan's CDR changes and loses the proper start time. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@134923 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-07-31 19:54:58 +00:00
}
}
for (;;) {
struct ast_channel *other; /* used later */
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
res = ast_channel_bridge(chan, peer, config, &f, &who);
Merged revisions 178828 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r178828 | murf | 2009-02-26 10:22:11 -0700 (Thu, 26 Feb 2009) | 34 lines Merged revisions 178804 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r178804 | murf | 2009-02-26 10:09:03 -0700 (Thu, 26 Feb 2009) | 28 lines This patch prevents the feature detection timeout from being cut in half. Because the ast_channel_bridge() call will return 0 and pass a frame pointer for both DTMF_BEGIN and DTMF_END, the feature_timer field in hte config struct is getting decremented twice, which effectively cuts the digittimeout in half. I added conditions to the if statement to only let DTMF_END frames to flow thru, which solved the problem. Also, when the frame pointer is null, let control flow thru-- this usually happens on timeouts. I added a comment to the code to explain what's going on and why. Many thanks to sodom for reporting this problem. Personnally, it always seemed like something was wrong with the featuredigittimeout, but I never could quite decide what... and was too busy to investigate. This bug forced the issue, and now we know. Sodom had other issues in 14515, but I couldn't reproduce them. If he still has problems, and wants to get them solved, he is welcome to reopen 14515. (closes issue #14515) Reported by: sodom Patches: 14515.patch uploaded by murf (license 17) Tested by: murf, sodom ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@178866 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-02-26 17:29:53 +00:00
/* When frame is not set, we are probably involved in a situation
where we've timed out.
When frame is set, we'll come this code twice; once for DTMF_BEGIN
and also for DTMF_END. If we flow into the following 'if' for both, then
our wait times are cut in half, as both will subtract from the
feature_timer. Not good!
*/
if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) {
/* Update time limit for next pass */
Merged revisions 43779 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ................ r43779 | russell | 2006-09-27 12:55:49 -0400 (Wed, 27 Sep 2006) | 50 lines Merged revisions 43778 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.2 ........ r43778 | russell | 2006-09-27 12:54:30 -0400 (Wed, 27 Sep 2006) | 42 lines Fix a problem that occurred if a user entered a digit that matched a bridge feature that was configured using multiple digits, and the digit that was pressed timed out in the feature digit timeout period. For example, if blind transfer is configured as '##', and a user presses just '#'. In this situation, the call would lock up and no longer pass any frames. (issue #7977 reported by festr, and issue #7982 reported by michaels and valuable input provided by mneuhauser and kuj. Fixed by me, with testing help and peer review from Joshua Colp). There are a couple of issues involved in this fix: 1) When ast_generic_bridge determines that there has been a timeout, it returned AST_BRIDGE_RETRY. Then, when ast_channel_bridge gets this result, it calls ast_generic_bridge over again with the same timestamp for the next event. This results in an endless loop of nothing until the call is terminated. This is resolved by simply changing ast_generic_bridge to return AST_BRIDGE_COMPLETE when it sees a timeout. 2) I also changed ast_channel_bridge such that if in the process of calculating the time until the next event, it knows a timeout has already occured, to immediately return AST_BRIDGE_COMPLETE instead of attempting to bridge the channels anyway. 3) In the process of testing the previous two changes, I ran into a problem in res_features where ast_channel_bridge would return because it determined that there was a timeout. However, ast_bridge_call in res_features would then determine by its own calculation that there was still 1 ms before the timeout really occurs. It would then proceed, and since the bridge broke out and did *not* return a frame, it interpreted this as the call was over and hung up the channels. The reason for this was because ast_bridge_call in res_features and ast_channel_bridge in channel.c were using different times for their calculations. channel.c uses the start_time on the bridge config, which is the time that the feature digit was recieved. However, res_features had another time, 'start', which was set right before calling ast_channel_bridge. 'start' will always be slightly after start_time in the bridge config, and sometimes enough to round up to one ms. This is fixed by making ast_bridge_call use the same time as ast_channel_bridge for the timeout calculation. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43780 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-27 16:57:44 +00:00
diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
if (res == AST_BRIDGE_RETRY) {
/* The feature fully timed out but has not been updated. Skip
* the potential round error from the diff calculation and
* explicitly set to expired. */
config->feature_timer = -1;
} else {
config->feature_timer -= diff;
}
if (hasfeatures) {
/* Running on backup config, meaning a feature might be being
activated, but that's no excuse to keep things going
indefinitely! */
if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) {
ast_debug(1, "Timed out, realtime this time!\n");
config->feature_timer = 0;
who = chan;
if (f)
ast_frfree(f);
f = NULL;
res = 0;
} else if (config->feature_timer <= 0) {
/* Not *really* out of time, just out of time for
digits to come in for features. */
ast_debug(1, "Timed out for feature!\n");
if (!ast_strlen_zero(peer_featurecode)) {
ast_dtmf_stream(chan, peer, peer_featurecode, 0, 0);
memset(peer_featurecode, 0, sizeof(peer_featurecode));
}
if (!ast_strlen_zero(chan_featurecode)) {
ast_dtmf_stream(peer, chan, chan_featurecode, 0, 0);
memset(chan_featurecode, 0, sizeof(chan_featurecode));
}
if (f)
ast_frfree(f);
hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
if (!hasfeatures) {
/* Restore original (possibly time modified) bridge config */
memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
memset(&backup_config, 0, sizeof(backup_config));
}
hadfeatures = hasfeatures;
/* Continue as we were */
continue;
Merged revisions 43779 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ................ r43779 | russell | 2006-09-27 12:55:49 -0400 (Wed, 27 Sep 2006) | 50 lines Merged revisions 43778 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.2 ........ r43778 | russell | 2006-09-27 12:54:30 -0400 (Wed, 27 Sep 2006) | 42 lines Fix a problem that occurred if a user entered a digit that matched a bridge feature that was configured using multiple digits, and the digit that was pressed timed out in the feature digit timeout period. For example, if blind transfer is configured as '##', and a user presses just '#'. In this situation, the call would lock up and no longer pass any frames. (issue #7977 reported by festr, and issue #7982 reported by michaels and valuable input provided by mneuhauser and kuj. Fixed by me, with testing help and peer review from Joshua Colp). There are a couple of issues involved in this fix: 1) When ast_generic_bridge determines that there has been a timeout, it returned AST_BRIDGE_RETRY. Then, when ast_channel_bridge gets this result, it calls ast_generic_bridge over again with the same timestamp for the next event. This results in an endless loop of nothing until the call is terminated. This is resolved by simply changing ast_generic_bridge to return AST_BRIDGE_COMPLETE when it sees a timeout. 2) I also changed ast_channel_bridge such that if in the process of calculating the time until the next event, it knows a timeout has already occured, to immediately return AST_BRIDGE_COMPLETE instead of attempting to bridge the channels anyway. 3) In the process of testing the previous two changes, I ran into a problem in res_features where ast_channel_bridge would return because it determined that there was a timeout. However, ast_bridge_call in res_features would then determine by its own calculation that there was still 1 ms before the timeout really occurs. It would then proceed, and since the bridge broke out and did *not* return a frame, it interpreted this as the call was over and hung up the channels. The reason for this was because ast_bridge_call in res_features and ast_channel_bridge in channel.c were using different times for their calculations. channel.c uses the start_time on the bridge config, which is the time that the feature digit was recieved. However, res_features had another time, 'start', which was set right before calling ast_channel_bridge. 'start' will always be slightly after start_time in the bridge config, and sometimes enough to round up to one ms. This is fixed by making ast_bridge_call use the same time as ast_channel_bridge for the timeout calculation. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43780 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-27 16:57:44 +00:00
} else if (!f) {
/* The bridge returned without a frame and there is a feature in progress.
* However, we don't think the feature has quite yet timed out, so just
* go back into the bridge. */
continue;
}
} else {
if (config->feature_timer <=0) {
/* We ran out of time */
config->feature_timer = 0;
who = chan;
if (f)
ast_frfree(f);
f = NULL;
res = 0;
}
}
}
if (res < 0) {
if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
Merged revisions 135821 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r135821 | murf | 2008-08-05 17:45:32 -0600 (Tue, 05 Aug 2008) | 42 lines Merged revisions 135799 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r135799 | murf | 2008-08-05 17:13:20 -0600 (Tue, 05 Aug 2008) | 34 lines (closes issue #12982) Reported by: bcnit Tested by: murf I discovered that also, in the previous bug fixes and changes, the cdr.conf 'unanswered' option is not being obeyed, so I fixed this. And, yes, there are two 'answer' times involved in this scenario, and I would agree with you, that the first answer time is the time that should appear in the CDR. (the second 'answer' time is the time that the bridge was begun). I made the necessary adjustments, recording the first answer time into the peer cdr, and then using that to override the bridge cdr's value. To get the 'unanswered' CDRs to appear, I purposely output them, using the dial cmd to mark them as DIALED (with a new flag), and outputting them if they bear that flag, and you are in the right mode. I also corrected one small mention of the Zap device to equally consider the dahdi device. I heavily tested 10-sec-wait macros in dial, and without the macro call; I tested hangups while the macro was running vs. letting the macro complete and the bridge form. Looks OK. Removed all the instrumentation and debug. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@135822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-08-05 23:52:14 +00:00
goto before_you_go;
}
if (!f || (f->frametype == AST_FRAME_CONTROL &&
(f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY ||
f->subclass == AST_CONTROL_CONGESTION))) {
res = -1;
break;
}
/* many things should be sent to the 'other' channel */
other = (who == chan) ? peer : chan;
if (f->frametype == AST_FRAME_CONTROL) {
switch (f->subclass) {
case AST_CONTROL_RINGING:
case AST_CONTROL_FLASH:
case -1:
ast_indicate(other, f->subclass);
break;
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
ast_indicate_data(other, f->subclass, f->data, f->datalen);
break;
case AST_CONTROL_OPTION:
aoh = f->data;
/* Forward option Requests */
if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) {
ast_channel_setoption(other, ntohs(aoh->option), aoh->data,
f->datalen - sizeof(struct ast_option_header), 0);
}
break;
}
} else if (f->frametype == AST_FRAME_DTMF_BEGIN) {
/* eat it */
} else if (f->frametype == AST_FRAME_DTMF) {
char *featurecode;
int sense;
hadfeatures = hasfeatures;
/* This cannot overrun because the longest feature is one shorter than our buffer */
if (who == chan) {
sense = FEATURE_SENSE_CHAN;
featurecode = chan_featurecode;
} else {
sense = FEATURE_SENSE_PEER;
featurecode = peer_featurecode;
}
/*! append the event to featurecode. we rely on the string being zero-filled, and
* not overflowing it.
* \todo XXX how do we guarantee the latter ?
*/
featurecode[strlen(featurecode)] = f->subclass;
/* Get rid of the frame before we start doing "stuff" with the channels */
ast_frfree(f);
f = NULL;
config->feature_timer = backup_config.feature_timer;
res = ast_feature_interpret(chan, peer, config, featurecode, sense);
switch(res) {
case FEATURE_RETURN_PASSDIGITS:
ast_dtmf_stream(other, who, featurecode, 0, 0);
/* Fall through */
case FEATURE_RETURN_SUCCESS:
memset(featurecode, 0, sizeof(chan_featurecode));
break;
}
if (res >= FEATURE_RETURN_PASSDIGITS) {
res = 0;
} else
break;
hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode);
if (hadfeatures && !hasfeatures) {
/* Restore backup */
memcpy(config, &backup_config, sizeof(struct ast_bridge_config));
memset(&backup_config, 0, sizeof(struct ast_bridge_config));
} else if (hasfeatures) {
if (!hadfeatures) {
/* Backup configuration */
memcpy(&backup_config, config, sizeof(struct ast_bridge_config));
/* Setup temporary config options */
config->play_warning = 0;
ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
config->warning_freq = 0;
config->warning_sound = NULL;
config->end_sound = NULL;
config->start_sound = NULL;
config->firstpass = 0;
}
config->start_time = ast_tvnow();
config->feature_timer = featuredigittimeout;
ast_debug(1, "Set time limit to %ld\n", config->feature_timer);
}
}
if (f)
ast_frfree(f);
}
Merged revisions 135821 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r135821 | murf | 2008-08-05 17:45:32 -0600 (Tue, 05 Aug 2008) | 42 lines Merged revisions 135799 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r135799 | murf | 2008-08-05 17:13:20 -0600 (Tue, 05 Aug 2008) | 34 lines (closes issue #12982) Reported by: bcnit Tested by: murf I discovered that also, in the previous bug fixes and changes, the cdr.conf 'unanswered' option is not being obeyed, so I fixed this. And, yes, there are two 'answer' times involved in this scenario, and I would agree with you, that the first answer time is the time that should appear in the CDR. (the second 'answer' time is the time that the bridge was begun). I made the necessary adjustments, recording the first answer time into the peer cdr, and then using that to override the bridge cdr's value. To get the 'unanswered' CDRs to appear, I purposely output them, using the dial cmd to mark them as DIALED (with a new flag), and outputting them if they bear that flag, and you are in the right mode. I also corrected one small mention of the Zap device to equally consider the dahdi device. I heavily tested 10-sec-wait macros in dial, and without the macro call; I tested hangups while the macro was running vs. letting the macro complete and the bridge form. Looks OK. Removed all the instrumentation and debug. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@135822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-08-05 23:52:14 +00:00
before_you_go:
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) {
ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */
if (bridge_cdr) {
ast_cdr_discard(bridge_cdr);
/* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */
}
return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */
}
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
if (config->end_bridge_callback) {
config->end_bridge_callback(config->end_bridge_callback_data);
}
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) &&
ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
struct ast_cdr *swapper = NULL;
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
char savelastapp[AST_MAX_EXTENSION];
char savelastdata[AST_MAX_EXTENSION];
char save_exten[AST_MAX_EXTENSION];
int save_prio;
int found = 0; /* set if we find at least one match */
Merged revisions 147518,147689,148000,148112,148268,148917,148988,149062,149131,149201,149205,149208 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r147518 | file | 2008-10-08 09:53:51 -0500 (Wed, 08 Oct 2008) | 9 lines Merged revisions 147517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147517 | file | 2008-10-08 11:51:42 -0300 (Wed, 08 Oct 2008) | 2 lines If we receive DTMF make sure that the state of the speech structure goes back to being not ready. (issue #LUMENVOX-8) ........ ................ r147689 | kpfleming | 2008-10-08 17:26:55 -0500 (Wed, 08 Oct 2008) | 9 lines Merged revisions 147681 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147681 | kpfleming | 2008-10-08 17:22:09 -0500 (Wed, 08 Oct 2008) | 3 lines when parsing a text configuration option, ensure that the buffer on the stack is actually large enough to hold the legal values of that option, and also ensure that sscanf() knows to stop parsing if it would overrun the buffer (without these changes, specifying "buffers=...,immediate" would overflow the buffer on the stack, and could not have worked as expected) ........ ................ r148000 | tilghman | 2008-10-09 14:39:34 -0500 (Thu, 09 Oct 2008) | 11 lines Merged revisions 147997 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147997 | tilghman | 2008-10-09 14:38:33 -0500 (Thu, 09 Oct 2008) | 4 lines When blank, callerid name and number should display "unknown caller" in voicemail emails. (Closes issue #13643) ........ ................ r148112 | mmichelson | 2008-10-09 18:15:33 -0500 (Thu, 09 Oct 2008) | 26 lines Merged revisions 146026 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r146026 | murf | 2008-10-03 12:12:54 -0500 (Fri, 03 Oct 2008) | 18 lines (closes issue #13579) Reported by: dwagner (closes issue #13584) Reported by: dwagner Tested by: murf, putnopvut The thought occurred to me that the res= from the extension spawn was ending up being returned from the bridge. "Thou shalt not poison the return value". Made the change and it appears to allow blind xfers to work as normal. If I'm wrong, reopen the bugs. But it looks good to me! Many thanks to putnopvut for helping me reproduce this! ........ ................ r148268 | tilghman | 2008-10-10 11:31:31 -0500 (Fri, 10 Oct 2008) | 14 lines Merged revisions 148257 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148257 | tilghman | 2008-10-10 11:25:31 -0500 (Fri, 10 Oct 2008) | 7 lines User not notified of temporary greeting, if ODBC storage is in use. (closes issue #13659) Reported by: moliveras Patches: 20081009__bug13659.diff.txt uploaded by Corydon76 (license 14) Tested by: moliveras ........ ................ r148917 | tilghman | 2008-10-14 12:46:48 -0500 (Tue, 14 Oct 2008) | 11 lines Merged revisions 148916 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148916 | tilghman | 2008-10-14 12:41:08 -0500 (Tue, 14 Oct 2008) | 4 lines Ensure that mail headers are 7-bit clean, even when UTF-8 characters are used in headers like 'Subject' and 'To'. Closes AST-107. ........ ................ r148988 | tilghman | 2008-10-14 14:03:44 -0500 (Tue, 14 Oct 2008) | 9 lines Merged revisions 148987 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148987 | tilghman | 2008-10-14 14:03:08 -0500 (Tue, 14 Oct 2008) | 2 lines Some compilers warn, some don't. Fixing. ........ ................ r149062 | tilghman | 2008-10-14 15:16:48 -0500 (Tue, 14 Oct 2008) | 13 lines Merged revisions 149061 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149061 | tilghman | 2008-10-14 15:09:06 -0500 (Tue, 14 Oct 2008) | 6 lines Check correct values in the return of ast_waitfor(); also, get rid of a possible memory leak. (closes issue #13658) Reported by: explidous Patch by: me ........ ................ r149131 | mmichelson | 2008-10-14 16:08:48 -0500 (Tue, 14 Oct 2008) | 15 lines Merged revisions 149130 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149130 | mmichelson | 2008-10-14 15:49:02 -0500 (Tue, 14 Oct 2008) | 7 lines Don't allow reserved characters to be used in register lines in sip.conf. (closes issue #13570) Reported by: putnopvut ........ ................ r149201 | mmichelson | 2008-10-14 17:41:13 -0500 (Tue, 14 Oct 2008) | 20 lines Merged revisions 149200 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149200 | mmichelson | 2008-10-14 17:40:42 -0500 (Tue, 14 Oct 2008) | 12 lines Update the queue with the correct number of calls and whether the call was completed within the service level when a transfer takes place. This way, we do not "break" the leastrecent and fewestcalls strategies by not logging a call until after the transferred call has ended. (closes issue #13395) Reported by: Marquis Patches: app_queue.c.transfer.patch uploaded by Marquis (license 32) ........ ................ r149205 | mmichelson | 2008-10-14 18:04:44 -0500 (Tue, 14 Oct 2008) | 20 lines Merged revisions 149204 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149204 | mmichelson | 2008-10-14 18:00:01 -0500 (Tue, 14 Oct 2008) | 12 lines Add a tolerance period for sync-triggered audiohooks so that if packetization of audio is close (but not equal) we don't end up flushing the audiohooks over small inconsistencies in synchronization. Related to issue #13005, and solves the issue for most people who were experiencing the problem. However, a small number of people are still experiencing the problem on long calls, so I am not closing the issue yet ........ ................ r149208 | mmichelson | 2008-10-14 18:15:04 -0500 (Tue, 14 Oct 2008) | 17 lines Merged revisions 149207 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149207 | mmichelson | 2008-10-14 18:10:26 -0500 (Tue, 14 Oct 2008) | 9 lines Call register_peer_exten even in the case that the peer's IP/port does not change. (closes issue #13309) Reported by: dimas Patches: v2-13309.patch uploaded by dimas (license 88) ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@160387 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-02 22:16:32 +00:00
int spawn_error = 0;
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
if (bridge_cdr && ast_opt_end_cdr_before_h_exten) {
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
ast_cdr_end(bridge_cdr);
}
/* swap the bridge cdr and the chan cdr for a moment, and let the endbridge
dialplan code operate on it */
ast_channel_lock(chan);
if (bridge_cdr) {
swapper = chan->cdr;
ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp));
ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata));
chan->cdr = bridge_cdr;
}
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
ast_copy_string(save_exten, chan->exten, sizeof(save_exten));
save_prio = chan->priority;
ast_copy_string(chan->exten, "h", sizeof(chan->exten));
chan->priority = 1;
ast_channel_unlock(chan);
Merged revisions 147518,147689,148000,148112,148268,148917,148988,149062,149131,149201,149205,149208 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r147518 | file | 2008-10-08 09:53:51 -0500 (Wed, 08 Oct 2008) | 9 lines Merged revisions 147517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147517 | file | 2008-10-08 11:51:42 -0300 (Wed, 08 Oct 2008) | 2 lines If we receive DTMF make sure that the state of the speech structure goes back to being not ready. (issue #LUMENVOX-8) ........ ................ r147689 | kpfleming | 2008-10-08 17:26:55 -0500 (Wed, 08 Oct 2008) | 9 lines Merged revisions 147681 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147681 | kpfleming | 2008-10-08 17:22:09 -0500 (Wed, 08 Oct 2008) | 3 lines when parsing a text configuration option, ensure that the buffer on the stack is actually large enough to hold the legal values of that option, and also ensure that sscanf() knows to stop parsing if it would overrun the buffer (without these changes, specifying "buffers=...,immediate" would overflow the buffer on the stack, and could not have worked as expected) ........ ................ r148000 | tilghman | 2008-10-09 14:39:34 -0500 (Thu, 09 Oct 2008) | 11 lines Merged revisions 147997 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147997 | tilghman | 2008-10-09 14:38:33 -0500 (Thu, 09 Oct 2008) | 4 lines When blank, callerid name and number should display "unknown caller" in voicemail emails. (Closes issue #13643) ........ ................ r148112 | mmichelson | 2008-10-09 18:15:33 -0500 (Thu, 09 Oct 2008) | 26 lines Merged revisions 146026 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r146026 | murf | 2008-10-03 12:12:54 -0500 (Fri, 03 Oct 2008) | 18 lines (closes issue #13579) Reported by: dwagner (closes issue #13584) Reported by: dwagner Tested by: murf, putnopvut The thought occurred to me that the res= from the extension spawn was ending up being returned from the bridge. "Thou shalt not poison the return value". Made the change and it appears to allow blind xfers to work as normal. If I'm wrong, reopen the bugs. But it looks good to me! Many thanks to putnopvut for helping me reproduce this! ........ ................ r148268 | tilghman | 2008-10-10 11:31:31 -0500 (Fri, 10 Oct 2008) | 14 lines Merged revisions 148257 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148257 | tilghman | 2008-10-10 11:25:31 -0500 (Fri, 10 Oct 2008) | 7 lines User not notified of temporary greeting, if ODBC storage is in use. (closes issue #13659) Reported by: moliveras Patches: 20081009__bug13659.diff.txt uploaded by Corydon76 (license 14) Tested by: moliveras ........ ................ r148917 | tilghman | 2008-10-14 12:46:48 -0500 (Tue, 14 Oct 2008) | 11 lines Merged revisions 148916 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148916 | tilghman | 2008-10-14 12:41:08 -0500 (Tue, 14 Oct 2008) | 4 lines Ensure that mail headers are 7-bit clean, even when UTF-8 characters are used in headers like 'Subject' and 'To'. Closes AST-107. ........ ................ r148988 | tilghman | 2008-10-14 14:03:44 -0500 (Tue, 14 Oct 2008) | 9 lines Merged revisions 148987 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148987 | tilghman | 2008-10-14 14:03:08 -0500 (Tue, 14 Oct 2008) | 2 lines Some compilers warn, some don't. Fixing. ........ ................ r149062 | tilghman | 2008-10-14 15:16:48 -0500 (Tue, 14 Oct 2008) | 13 lines Merged revisions 149061 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149061 | tilghman | 2008-10-14 15:09:06 -0500 (Tue, 14 Oct 2008) | 6 lines Check correct values in the return of ast_waitfor(); also, get rid of a possible memory leak. (closes issue #13658) Reported by: explidous Patch by: me ........ ................ r149131 | mmichelson | 2008-10-14 16:08:48 -0500 (Tue, 14 Oct 2008) | 15 lines Merged revisions 149130 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149130 | mmichelson | 2008-10-14 15:49:02 -0500 (Tue, 14 Oct 2008) | 7 lines Don't allow reserved characters to be used in register lines in sip.conf. (closes issue #13570) Reported by: putnopvut ........ ................ r149201 | mmichelson | 2008-10-14 17:41:13 -0500 (Tue, 14 Oct 2008) | 20 lines Merged revisions 149200 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149200 | mmichelson | 2008-10-14 17:40:42 -0500 (Tue, 14 Oct 2008) | 12 lines Update the queue with the correct number of calls and whether the call was completed within the service level when a transfer takes place. This way, we do not "break" the leastrecent and fewestcalls strategies by not logging a call until after the transferred call has ended. (closes issue #13395) Reported by: Marquis Patches: app_queue.c.transfer.patch uploaded by Marquis (license 32) ........ ................ r149205 | mmichelson | 2008-10-14 18:04:44 -0500 (Tue, 14 Oct 2008) | 20 lines Merged revisions 149204 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149204 | mmichelson | 2008-10-14 18:00:01 -0500 (Tue, 14 Oct 2008) | 12 lines Add a tolerance period for sync-triggered audiohooks so that if packetization of audio is close (but not equal) we don't end up flushing the audiohooks over small inconsistencies in synchronization. Related to issue #13005, and solves the issue for most people who were experiencing the problem. However, a small number of people are still experiencing the problem on long calls, so I am not closing the issue yet ........ ................ r149208 | mmichelson | 2008-10-14 18:15:04 -0500 (Tue, 14 Oct 2008) | 17 lines Merged revisions 149207 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149207 | mmichelson | 2008-10-14 18:10:26 -0500 (Tue, 14 Oct 2008) | 9 lines Call register_peer_exten even in the case that the peer's IP/port does not change. (closes issue #13309) Reported by: dimas Patches: v2-13309.patch uploaded by dimas (license 88) ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@160387 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-02 22:16:32 +00:00
while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) {
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
chan->priority++;
}
Merged revisions 147518,147689,148000,148112,148268,148917,148988,149062,149131,149201,149205,149208 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r147518 | file | 2008-10-08 09:53:51 -0500 (Wed, 08 Oct 2008) | 9 lines Merged revisions 147517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147517 | file | 2008-10-08 11:51:42 -0300 (Wed, 08 Oct 2008) | 2 lines If we receive DTMF make sure that the state of the speech structure goes back to being not ready. (issue #LUMENVOX-8) ........ ................ r147689 | kpfleming | 2008-10-08 17:26:55 -0500 (Wed, 08 Oct 2008) | 9 lines Merged revisions 147681 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147681 | kpfleming | 2008-10-08 17:22:09 -0500 (Wed, 08 Oct 2008) | 3 lines when parsing a text configuration option, ensure that the buffer on the stack is actually large enough to hold the legal values of that option, and also ensure that sscanf() knows to stop parsing if it would overrun the buffer (without these changes, specifying "buffers=...,immediate" would overflow the buffer on the stack, and could not have worked as expected) ........ ................ r148000 | tilghman | 2008-10-09 14:39:34 -0500 (Thu, 09 Oct 2008) | 11 lines Merged revisions 147997 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r147997 | tilghman | 2008-10-09 14:38:33 -0500 (Thu, 09 Oct 2008) | 4 lines When blank, callerid name and number should display "unknown caller" in voicemail emails. (Closes issue #13643) ........ ................ r148112 | mmichelson | 2008-10-09 18:15:33 -0500 (Thu, 09 Oct 2008) | 26 lines Merged revisions 146026 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r146026 | murf | 2008-10-03 12:12:54 -0500 (Fri, 03 Oct 2008) | 18 lines (closes issue #13579) Reported by: dwagner (closes issue #13584) Reported by: dwagner Tested by: murf, putnopvut The thought occurred to me that the res= from the extension spawn was ending up being returned from the bridge. "Thou shalt not poison the return value". Made the change and it appears to allow blind xfers to work as normal. If I'm wrong, reopen the bugs. But it looks good to me! Many thanks to putnopvut for helping me reproduce this! ........ ................ r148268 | tilghman | 2008-10-10 11:31:31 -0500 (Fri, 10 Oct 2008) | 14 lines Merged revisions 148257 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148257 | tilghman | 2008-10-10 11:25:31 -0500 (Fri, 10 Oct 2008) | 7 lines User not notified of temporary greeting, if ODBC storage is in use. (closes issue #13659) Reported by: moliveras Patches: 20081009__bug13659.diff.txt uploaded by Corydon76 (license 14) Tested by: moliveras ........ ................ r148917 | tilghman | 2008-10-14 12:46:48 -0500 (Tue, 14 Oct 2008) | 11 lines Merged revisions 148916 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148916 | tilghman | 2008-10-14 12:41:08 -0500 (Tue, 14 Oct 2008) | 4 lines Ensure that mail headers are 7-bit clean, even when UTF-8 characters are used in headers like 'Subject' and 'To'. Closes AST-107. ........ ................ r148988 | tilghman | 2008-10-14 14:03:44 -0500 (Tue, 14 Oct 2008) | 9 lines Merged revisions 148987 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r148987 | tilghman | 2008-10-14 14:03:08 -0500 (Tue, 14 Oct 2008) | 2 lines Some compilers warn, some don't. Fixing. ........ ................ r149062 | tilghman | 2008-10-14 15:16:48 -0500 (Tue, 14 Oct 2008) | 13 lines Merged revisions 149061 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149061 | tilghman | 2008-10-14 15:09:06 -0500 (Tue, 14 Oct 2008) | 6 lines Check correct values in the return of ast_waitfor(); also, get rid of a possible memory leak. (closes issue #13658) Reported by: explidous Patch by: me ........ ................ r149131 | mmichelson | 2008-10-14 16:08:48 -0500 (Tue, 14 Oct 2008) | 15 lines Merged revisions 149130 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149130 | mmichelson | 2008-10-14 15:49:02 -0500 (Tue, 14 Oct 2008) | 7 lines Don't allow reserved characters to be used in register lines in sip.conf. (closes issue #13570) Reported by: putnopvut ........ ................ r149201 | mmichelson | 2008-10-14 17:41:13 -0500 (Tue, 14 Oct 2008) | 20 lines Merged revisions 149200 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149200 | mmichelson | 2008-10-14 17:40:42 -0500 (Tue, 14 Oct 2008) | 12 lines Update the queue with the correct number of calls and whether the call was completed within the service level when a transfer takes place. This way, we do not "break" the leastrecent and fewestcalls strategies by not logging a call until after the transferred call has ended. (closes issue #13395) Reported by: Marquis Patches: app_queue.c.transfer.patch uploaded by Marquis (license 32) ........ ................ r149205 | mmichelson | 2008-10-14 18:04:44 -0500 (Tue, 14 Oct 2008) | 20 lines Merged revisions 149204 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149204 | mmichelson | 2008-10-14 18:00:01 -0500 (Tue, 14 Oct 2008) | 12 lines Add a tolerance period for sync-triggered audiohooks so that if packetization of audio is close (but not equal) we don't end up flushing the audiohooks over small inconsistencies in synchronization. Related to issue #13005, and solves the issue for most people who were experiencing the problem. However, a small number of people are still experiencing the problem on long calls, so I am not closing the issue yet ........ ................ r149208 | mmichelson | 2008-10-14 18:15:04 -0500 (Tue, 14 Oct 2008) | 17 lines Merged revisions 149207 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r149207 | mmichelson | 2008-10-14 18:10:26 -0500 (Tue, 14 Oct 2008) | 9 lines Call register_peer_exten even in the case that the peer's IP/port does not change. (closes issue #13309) Reported by: dimas Patches: v2-13309.patch uploaded by dimas (license 88) ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@160387 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-02 22:16:32 +00:00
if (found && spawn_error) {
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
/* Something bad happened, or a hangup has been requested. */
ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name);
}
/* swap it back */
ast_channel_lock(chan);
ast_copy_string(chan->exten, save_exten, sizeof(chan->exten));
chan->priority = save_prio;
if (bridge_cdr) {
if (chan->cdr == bridge_cdr) {
chan->cdr = swapper;
} else {
bridge_cdr = NULL;
}
}
if (chan->priority != 1 || !spawn_error) {
ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN);
}
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
ast_channel_unlock(chan);
/* protect the lastapp/lastdata against the effects of the hangup/dialplan code */
if (bridge_cdr) {
ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp));
ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata));
}
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
Merged revisions 142676 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r142676 | murf | 2008-09-11 22:50:48 -0600 (Thu, 11 Sep 2008) | 40 lines Merged revisions 142675 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r142675 | murf | 2008-09-11 22:29:34 -0600 (Thu, 11 Sep 2008) | 29 lines Tested by: sergee, murf, chris-mac, andrew, KNK This is a "second attempt" to restore the previous "endbeforeh" behavior in 1.4 and up. In order to capture information concerning all the legs of transfers in all their infinite combinations, I was forced to this particular solution by a chain of logical necessities, the first being that I was not allowed to rewrite the CDR mechanism from the ground up! This change basically leaves the original machinery alone, which allows IVR and local channel type situations to generate CDR's as normal, but a channel flag can be set to suppress the normal running of the h exten. That flag would be set by the code that runs the h exten from the ast_bridge_call routine, to prevent the h exten from being run twice. Also, a flag in the ast_bridge_config struct passed into ast_bridge_call can be used to suppress the running of the h exten in that routine. This would happen, for instance, if you use the 'g' option in the Dial app. Running this routine 'early' allows not only the CDR() func to be used in the h extension for reading CDR variables, but also allows them to be modified before the CDR is posted to the backends. While I dearly hope that this patch overcomes all problems, and introduces no new problems, reality suggests that surely someone will have problems. In this case, please re-open 13251 (or 13289), and we'll see if we can't fix any remaining issues. ** trunk note: some code to suppress the h exten being run from app_queue was added; for the 'continue' option available only in trunk/1.6.x. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@142677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-09-12 04:58:38 +00:00
}
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
/* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */
new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */
if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED))
ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED);
/* we can post the bridge CDR at this point */
if (bridge_cdr) {
ast_cdr_end(bridge_cdr);
ast_cdr_detach(bridge_cdr);
}
/* do a specialized reset on the beginning channel
CDR's, if they still exist, so as not to mess up
issues in future bridges;
Here are the rules of the game:
1. The chan and peer channel pointers will not change
during the life of the bridge.
2. But, in transfers, the channel names will change.
between the time the bridge is started, and the
time the channel ends.
Usually, when a channel changes names, it will
also change CDR pointers.
3. Usually, only one of the two channels (chan or peer)
will change names.
4. Usually, if a channel changes names during a bridge,
it is because of a transfer. Usually, in these situations,
it is normal to see 2 bridges running simultaneously, and
it is not unusual to see the two channels that change
swapped between bridges.
5. After a bridge occurs, we have 2 or 3 channels' CDRs
to attend to; if the chan or peer changed names,
we have the before and after attached CDR's.
*/
if (new_chan_cdr) {
struct ast_channel *chan_ptr = NULL;
if (strcasecmp(orig_channame, chan->name) != 0) {
/* old channel */
chan_ptr = ast_get_channel_by_name_locked(orig_channame);
if (chan_ptr) {
if (!ast_bridged_channel(chan_ptr)) {
struct ast_cdr *cur;
for (cur = chan_ptr->cdr; cur; cur = cur->next) {
if (cur == chan_cdr) {
break;
}
}
if (cur)
ast_cdr_specialized_reset(chan_cdr,0);
}
ast_channel_unlock(chan_ptr);
}
/* new channel */
ast_cdr_specialized_reset(new_chan_cdr,0);
} else {
ast_cdr_specialized_reset(chan_cdr,0); /* nothing changed, reset the chan_cdr */
}
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
}
{
struct ast_channel *chan_ptr = NULL;
new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */
if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED))
ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */
if (strcasecmp(orig_peername, peer->name) != 0) {
/* old channel */
chan_ptr = ast_get_channel_by_name_locked(orig_peername);
if (chan_ptr) {
if (!ast_bridged_channel(chan_ptr)) {
struct ast_cdr *cur;
for (cur = chan_ptr->cdr; cur; cur = cur->next) {
if (cur == peer_cdr) {
break;
}
}
if (cur)
ast_cdr_specialized_reset(peer_cdr,0);
}
ast_channel_unlock(chan_ptr);
}
/* new channel */
ast_cdr_specialized_reset(new_peer_cdr,0);
} else {
ast_cdr_specialized_reset(peer_cdr,0); /* nothing changed, reset the peer_cdr */
}
Merged revisions 135821 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r135821 | murf | 2008-08-05 17:45:32 -0600 (Tue, 05 Aug 2008) | 42 lines Merged revisions 135799 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r135799 | murf | 2008-08-05 17:13:20 -0600 (Tue, 05 Aug 2008) | 34 lines (closes issue #12982) Reported by: bcnit Tested by: murf I discovered that also, in the previous bug fixes and changes, the cdr.conf 'unanswered' option is not being obeyed, so I fixed this. And, yes, there are two 'answer' times involved in this scenario, and I would agree with you, that the first answer time is the time that should appear in the CDR. (the second 'answer' time is the time that the bridge was begun). I made the necessary adjustments, recording the first answer time into the peer cdr, and then using that to override the bridge cdr's value. To get the 'unanswered' CDRs to appear, I purposely output them, using the dial cmd to mark them as DIALED (with a new flag), and outputting them if they bear that flag, and you are in the right mode. I also corrected one small mention of the Zap device to equally consider the dahdi device. I heavily tested 10-sec-wait macros in dial, and without the macro call; I tested hangups while the macro was running vs. letting the macro complete and the bridge form. Looks OK. Removed all the instrumentation and debug. ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@135822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-08-05 23:52:14 +00:00
}
Merged revisions 172063 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172063 | murf | 2009-01-28 13:31:06 -0700 (Wed, 28 Jan 2009) | 52 lines Merged revisions 172030 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172030 | murf | 2009-01-28 11:51:16 -0700 (Wed, 28 Jan 2009) | 46 lines This patch fixes h-exten running misbehavior in manager-redirected situations. What it does: 1. A new Flag value is defined in include/asterisk/channel.h, AST_FLAG_BRIDGE_HANGUP_DONT, which used as a messenge to the bridge hangup exten code not to run the h-exten there (nor publish the bridge cdr there). It will done at the pbx-loop level instead. 2. In the manager Redirect code, I set this flag on the channel if the channel has a non-null pbx pointer. I did the same for the second (chan2) channel, which gets run if name2 is set... and the first succeeds. 3. I restored the ending of the cdr for the pbx loop h-exten running code. Don't know why it was removed in the first place. 4. The first attempt at the fix for this bug was to place code directly in the async_goto routine, which was called from a large number of places, and could affect a large number of cases, so I tested that fix against a fair number of transfer scenarios, both with and without the patch. In the process, I saw that putting the fix in async_goto seemed not to affect any of the blind or attended scenarios, but still, I was was highly concerned that some other scenarios I had not tested might be negatively impacted, so I refined the patch to its current scope, and jmls tested both. In the process, tho, I saw that blind xfers in one situation, when the one-touch blind-xfer feature is used by the peer, we got strange h-exten behavior. So, I inserted code to swap CDRs and to set the HANGUP_DONT field, to get uniform behavior. 5. I added code to the bridge to obey the HANGUP_DONT flag, skipping both publishing the bridge CDR, and running the h-exten; they will be done at the pbx-loop (higher) level instead. 6. I removed all the debug logs from the patch before committing. 7. I moved the AUTOLOOP set/reset in the h-exten code in res_features so it's only done if the h-exten is going to be run. A very minor performance improvement, but technically correct. (closes issue #14241) Reported by: jmls Patches: 14241_redirect_no_bridgeCDR_or_h_exten_via_transfer uploaded by murf (license 17) Tested by: murf, jmls ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-28 20:41:45 +00:00
return res;
}
/*! \brief Output parking event to manager */
static void post_manager_event(const char *s, struct parkeduser *pu)
{
manager_event(EVENT_FLAG_CALL, s,
"Exten: %s\r\n"
"Channel: %s\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n\r\n",
pu->parkingexten,
pu->chan->name,
S_OR(pu->chan->cid.cid_num, "<unknown>"),
S_OR(pu->chan->cid.cid_name, "<unknown>")
);
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
static char *callback_dialoptions(struct ast_flags *features_callee, struct ast_flags *features_caller, char *options, size_t len)
{
int i = 0;
enum {
OPT_CALLEE_REDIRECT = 't',
OPT_CALLER_REDIRECT = 'T',
OPT_CALLEE_AUTOMON = 'w',
OPT_CALLER_AUTOMON = 'W',
OPT_CALLEE_DISCONNECT = 'h',
OPT_CALLER_DISCONNECT = 'H',
OPT_CALLEE_PARKCALL = 'k',
OPT_CALLER_PARKCALL = 'K',
};
memset(options, 0, len);
if (ast_test_flag(features_caller, AST_FEATURE_REDIRECT) && i < len) {
options[i++] = OPT_CALLER_REDIRECT;
}
if (ast_test_flag(features_caller, AST_FEATURE_AUTOMON) && i < len) {
options[i++] = OPT_CALLER_AUTOMON;
}
if (ast_test_flag(features_caller, AST_FEATURE_DISCONNECT) && i < len) {
options[i++] = OPT_CALLER_DISCONNECT;
}
if (ast_test_flag(features_caller, AST_FEATURE_PARKCALL) && i < len) {
options[i++] = OPT_CALLER_PARKCALL;
}
if (ast_test_flag(features_callee, AST_FEATURE_REDIRECT) && i < len) {
options[i++] = OPT_CALLEE_REDIRECT;
}
if (ast_test_flag(features_callee, AST_FEATURE_AUTOMON) && i < len) {
options[i++] = OPT_CALLEE_AUTOMON;
}
if (ast_test_flag(features_callee, AST_FEATURE_DISCONNECT) && i < len) {
options[i++] = OPT_CALLEE_DISCONNECT;
}
if (ast_test_flag(features_callee, AST_FEATURE_PARKCALL) && i < len) {
options[i++] = OPT_CALLEE_PARKCALL;
}
return options;
}
/*!
* \brief Take care of parked calls and unpark them if needed
* \param ignore unused var.
*
* Start inf loop, lock parking lot, check if any parked channels have gone above timeout
* if so, remove channel from parking lot and return it to the extension that parked it.
* Check if parked channel decided to hangup, wait until next FD via select().
*/
static void *do_parking_thread(void *ignore)
{
char parkingslot[AST_MAX_EXTENSION];
fd_set rfds, efds; /* results from previous select, to be preserved across loops. */
FD_ZERO(&rfds);
FD_ZERO(&efds);
for (;;) {
struct parkeduser *pu;
int ms = -1; /* select timeout, uninitialized */
int max = -1; /* max fd, none there yet */
fd_set nrfds, nefds; /* args for the next select */
FD_ZERO(&nrfds);
FD_ZERO(&nefds);
AST_LIST_LOCK(&parkinglot);
AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
struct ast_channel *chan = pu->chan; /* shorthand */
int tms; /* timeout for this item */
int x; /* fd index in channel */
struct ast_context *con;
if (pu->notquiteyet) /* Pretend this one isn't here yet */
continue;
tms = ast_tvdiff_ms(ast_tvnow(), pu->start);
if (tms > pu->parkingtime) {
ast_indicate(chan, AST_CONTROL_UNHOLD);
/* Get chan, exten from derived kludge */
if (pu->peername[0]) {
char *peername = ast_strdupa(pu->peername);
char *cp = strrchr(peername, '-');
char peername_flat[AST_MAX_EXTENSION]; /* using something like DAHDI/52 for an extension name is NOT a good idea */
int i;
if (cp)
*cp = 0;
ast_copy_string(peername_flat,peername,sizeof(peername_flat));
for(i=0; peername_flat[i] && i < AST_MAX_EXTENSION; i++) {
if (peername_flat[i] == '/')
peername_flat[i]= '0';
}
Merged revisions 130145 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Merging this rev from trunk to 1.6.0 was not simple. Why? Because we've enhanced trunk to do a [fast] merge-and-delete operation which also solved problems with contexts having entries from different registrars. Fast as in the amount of time the contexts are locked down. That *is* fast, but traversing the entire dialplan looking for priorities to delete takes more time overall. This particular fix involved pulling in those enhancements from trunk, along with all the various fixes and refinements made along the way. Merging all this from trunk into 1.6 involved: a. mergetrunk6 in the stuff from 130145; b. revert all but the prop changes c. catalog all revisions to pbx.c since 1.6.0 was forked (at rev 105596). d. catalog all revisions to pbx.c in trunk since 1.6.0 was forked, making special note of all revs that were not merged into 1.6.0. e. study each rev in trunk not applied to 1.6.0, and determine if it was involved in the merge_and_delete enhancements in trunk. 25 commits were done in 1.6.0, all but one (106306) was a merge from trunk. Trunk had 22 additional changes, of which 7 were involved in the merge_and_delete enhancements: 106757 108894 109169 116461 123358 130145 130297 f. Go to trunk and collect patches, one by one, of the changes made by each rev across the entire source tree, using svn diff -c <num> > pfile g. Apply each patch in order to 1.6.0, and resolve all failures and compilation problems before proceding to the next patch. h. test the stuff. i. profit! ........ r130145 | murf | 2008-07-11 12:24:31 -0600 (Fri, 11 Jul 2008) | 40 lines (closes issue #13041) Reported by: eliel Tested by: murf (closes issue #12960) Reported by: mnicholson In this 'omnibus' fix, I **think** I solved both the problem in 13041, where unloading pbx_ael.so caused crashes, or incomplete removal of previous registrar'ed entries. And I added code to completely remove all includes, switches, and ignorepats that had a matching registrar entry, which should appease 12960. I also added a lot of seemingly useless brackets around single statement if's, which helped debug so much that I'm leaving them there. I added a routine to check the correlation between the extension tree lists and the hashtab tables. It can be amazingly helpful when you have lots of dialplan stuff, and need to narrow down where a problem is occurring. It's ifdef'd out by default. I cleaned up the code around the new CIDmatch code. It was leaving hanging extens with bad ptrs, getting confused over which objects to remove, etc. I tightened up the code and changed the call to remove_exten in the merge_and_delete code. I added more conditions to check for empty context worthy of deletion. It's not empty if there are any includes, switches, or ignorepats present. If I've missed anything, please re-open this bug, and be prepared to supply example dialplan code. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@130946 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-07-15 13:14:07 +00:00
con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
if (!con)
ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
if (con) {
char returnexten[AST_MAX_EXTENSION];
struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures = NULL;
ast_channel_lock(chan);
if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
dialfeatures = features_datastore->data;
ast_channel_unlock(chan);
if (!strncmp(peername, "Parked/", 7)) {
peername += 7;
}
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
if (dialfeatures) {
char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, callback_dialoptions(&(dialfeatures->features_callee), &(dialfeatures->features_caller), buf, sizeof(buf)));
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
} else { /* Existing default */
snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername);
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
}
ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
}
if (comebacktoorigin) {
set_c_e_p(chan, parking_con_dial, peername_flat, 1);
} else {
ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
pbx_builtin_setvar_helper(pu->chan, "PARKINGSLOT", parkingslot);
set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1);
}
} else {
/* They've been waiting too long, send them back to where they came. Theoretically they
should have their original extensions and such, but we copy to be on the safe side */
set_c_e_p(chan, pu->context, pu->exten, pu->priority);
}
post_manager_event("ParkedCallTimeOut", pu);
ast_verb(2, "Timeout for %s parked on %d. Returning to %s,%s,%d\n", chan->name, pu->parkingnum, chan->context, chan->exten, chan->priority);
/* Start up the PBX, or hang them up */
if (ast_pbx_start(chan)) {
ast_log(LOG_WARNING, "Unable to restart the PBX for user on '%s', hanging them up...\n", chan->name);
ast_hangup(chan);
}
/* And take them out of the parking lot */
AST_LIST_REMOVE_CURRENT(list);
con = ast_context_find(parking_con);
if (con) {
if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
else
notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
ast_free(pu);
} else { /* still within parking time, process descriptors */
for (x = 0; x < AST_MAX_FDS; x++) {
struct ast_frame *f;
if (chan->fds[x] == -1 || (!FD_ISSET(chan->fds[x], &rfds) && !FD_ISSET(chan->fds[x], &efds)))
continue; /* nothing on this descriptor */
if (FD_ISSET(chan->fds[x], &efds))
ast_set_flag(chan, AST_FLAG_EXCEPTION);
else
ast_clear_flag(chan, AST_FLAG_EXCEPTION);
chan->fdno = x;
/* See if they need servicing */
f = ast_read(chan);
if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP)) {
if (f)
ast_frfree(f);
post_manager_event("ParkedCallGiveUp", pu);
/* There's a problem, hang them up*/
ast_verb(2, "%s got tired of being parked\n", chan->name);
ast_hangup(chan);
/* And take them out of the parking lot */
AST_LIST_REMOVE_CURRENT(list);
con = ast_context_find(parking_con);
if (con) {
if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
else
notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
ast_free(pu);
break;
} else {
/*! \todo XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
ast_frfree(f);
if (pu->moh_trys < 3 && !chan->generatordata) {
ast_debug(1, "MOH on parked call stopped by outside source. Restarting.\n");
ast_indicate_data(chan, AST_CONTROL_HOLD,
S_OR(parkmohclass, NULL),
!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
pu->moh_trys++;
}
goto std; /*! \todo XXX Ick: jumping into an else statement??? XXX */
}
} /* end for */
if (x >= AST_MAX_FDS) {
std: for (x=0; x<AST_MAX_FDS; x++) { /* mark fds for next round */
if (chan->fds[x] > -1) {
FD_SET(chan->fds[x], &nrfds);
FD_SET(chan->fds[x], &nefds);
if (chan->fds[x] > max)
max = chan->fds[x];
}
}
/* Keep track of our shortest wait */
if (tms < ms || ms < 0)
ms = tms;
}
}
} /* end while */
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&parkinglot);
rfds = nrfds;
efds = nefds;
{
struct timeval tv = ast_samp2tv(ms, 1000);
/* Wait for something to happen */
ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
}
pthread_testcancel();
}
return NULL; /* Never reached */
}
/*! \brief Park a call */
static int park_call_exec(struct ast_channel *chan, void *data)
{
char *orig_chan_name = ast_strdupa(chan->name);
char orig_exten[AST_MAX_EXTENSION];
int orig_priority = chan->priority;
/* Data is unused at the moment but could contain a parking
lot context eventually */
int res = 0;
ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten));
/* Setup the exten/priority to be s/1 since we don't know
where this call should return */
strcpy(chan->exten, "s");
chan->priority = 1;
/* Answer if call is not up */
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
/* Sleep to allow VoIP streams to settle down */
if (!res)
res = ast_safe_sleep(chan, 1000);
/* Park the call */
if (!res) {
res = masq_park_call_announce(chan, chan, 0, NULL, orig_chan_name);
/* Continue on in the dialplan */
if (res == 1) {
ast_copy_string(chan->exten, orig_exten, sizeof(chan->exten));
chan->priority = orig_priority;
res = 0;
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
} else if (!res) {
res = 1;
}
}
return res;
}
/*! \brief Pickup parked call */
static int park_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_channel *peer=NULL;
struct parkeduser *pu;
struct ast_context *con;
int park = 0;
struct ast_bridge_config config;
if (data)
park = atoi((char *)data);
AST_LIST_LOCK(&parkinglot);
AST_LIST_TRAVERSE_SAFE_BEGIN(&parkinglot, pu, list) {
if (!data || pu->parkingnum == park) {
AST_LIST_REMOVE_CURRENT(list);
break;
}
}
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&parkinglot);
if (pu) {
peer = pu->chan;
con = ast_context_find(parking_con);
if (con) {
if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0))
ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
else
notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_NOT_INUSE);
} else
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
manager_event(EVENT_FLAG_CALL, "UnParkedCall",
"Exten: %s\r\n"
"Channel: %s\r\n"
"From: %s\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n",
pu->parkingexten, pu->chan->name, chan->name,
S_OR(pu->chan->cid.cid_num, "<unknown>"),
S_OR(pu->chan->cid.cid_name, "<unknown>")
);
ast_free(pu);
}
/* JK02: it helps to answer the channel if not already up */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
if (peer) {
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures = NULL;
/* Play a courtesy to the source(s) configured to prefix the bridge connecting */
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
if (!ast_strlen_zero(courtesytone)) {
int error = 0;
ast_indicate(peer, AST_CONTROL_UNHOLD);
if (parkedplay == 0) {
error = ast_stream_and_wait(chan, courtesytone, "");
} else if (parkedplay == 1) {
error = ast_stream_and_wait(peer, courtesytone, "");
} else if (parkedplay == 2) {
if (!ast_streamfile(chan, courtesytone, chan->language) &&
!ast_streamfile(peer, courtesytone, chan->language)) {
/*! \todo XXX we would like to wait on both! */
res = ast_waitstream(chan, "");
if (res >= 0)
res = ast_waitstream(peer, "");
if (res < 0)
error = 1;
}
}
if (error) {
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
ast_hangup(peer);
return -1;
}
} else
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
ast_indicate(peer, AST_CONTROL_UNHOLD);
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
ast_hangup(peer);
return -1;
}
/* This runs sorta backwards, since we give the incoming channel control, as if it
were the person called. */
ast_verb(3, "Channel %s connected to parked call %d\n", chan->name, park);
pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
ast_cdr_setdestchan(chan->cdr, peer->name);
memset(&config, 0, sizeof(struct ast_bridge_config));
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
/* Get datastore for peer and apply it's features to the callee side of the bridge config */
ast_channel_lock(peer);
if ((features_datastore = ast_channel_datastore_find(peer, &dial_features_info, NULL))) {
dialfeatures = features_datastore->data;
}
ast_channel_unlock(peer);
if (dialfeatures) {
ast_copy_flags(&(config.features_callee), dialfeatures->is_caller ? &(dialfeatures->features_caller) : &(dialfeatures->features_callee), AST_FLAGS_ALL);
}
if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLEE) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
}
if ((parkedcalltransfers == AST_FEATURE_FLAG_BYCALLER) || (parkedcalltransfers == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
}
if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
}
if ((parkedcallreparking == AST_FEATURE_FLAG_BYCALLER) || (parkedcallreparking == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
}
if ((parkedcallhangup == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
}
if ((parkedcallhangup == AST_FEATURE_FLAG_BYCALLER) || (parkedcallhangup == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
}
if ((parkedcallrecording == AST_FEATURE_FLAG_BYCALLEE) || (parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
}
if ((parkedcallrecording == AST_FEATURE_FLAG_BYCALLER) || (parkedcallrecording == AST_FEATURE_FLAG_BYBOTH)) {
ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
}
res = ast_bridge_call(chan, peer, &config);
pbx_builtin_setvar_helper(chan, "PARKEDCHANNEL", peer->name);
ast_cdr_setdestchan(chan->cdr, peer->name);
/* Simulate the PBX hanging up */
Merged revisions 166665 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Due to non-symmetrical updating, I had some fairly interesting conflicts to straighten out in this release. The changes were such that I was compelled to run thru all the same tests as trunk, which turned up some problems, which I fixed. ................ r166665 | murf | 2008-12-23 11:13:49 -0700 (Tue, 23 Dec 2008) | 153 lines Merged revisions 166093 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 In order to merge this 1.4 patch into trunk, I had to resolve some conflicts and wait for Russell to make some changes to res_agi. I re-ran all the tests; 39 calls in all, and made fairly careful notes and comparisons: I don't want this to blow up some aspect of asterisk; I completely removed the KEEPALIVE from the pbx.h decls. The first 3 scenarios involving feature park; feature xfer to 700; hookflash park to Park() app call all behave the same, don't appear to leave hung channels, and no crashes. ........ r166093 | murf | 2008-12-19 15:30:32 -0700 (Fri, 19 Dec 2008) | 131 lines This merges the masqpark branch into 1.4 These changes eliminate the need for (and use of) the KEEPALIVE return code in res_features.c; There are other places that use this result code for similar purposes at a higher level, these appear to be left alone in 1.4, but attacked in trunk. The reason these changes are being made in 1.4, is that parking ends a channel's life, in some situations, and the code in the bridge (and some other places), was not checking the result code properly, and dereferencing the channel pointer, which could lead to memory corruption and crashes. Calling the masq_park function eliminates this danger in higher levels. A series of previous commits have replaced some parking calls with masq_park, but this patch puts them ALL to rest, (except one, purposely left alone because a masquerade is done anyway), and gets rid of the code that tests the KEEPALIVE result, and the NOHANGUP_PEER result codes. While bug 13820 inspired this work, this patch does not solve all the problems mentioned there. I have tested this patch (again) to make sure I have not introduced regressions. Crashes that occurred when a parked party hung up while the parking party was listening to the numbers of the parking stall being assigned, is eliminated. These are the cases where parking code may be activated: 1. Feature one touch (eg. *3) 2. Feature blind xfer to parking lot (eg ##700) 3. Run Park() app from dialplan (eg sip xfer to 700) (eg. dahdi hookflash xfer to 700) 4. Run Park via manager. The interesting testing cases for parking are: I. A calls B, A parks B a. B hangs up while A is getting the numbers announced. b. B hangs up after A gets the announcement, but before the parking time expires c. B waits, time expires, A is redialed, A answers, B and A are connected, after which, B hangs up. d. C picks up B while still in parking lot. II. A calls B, B parks A a. A hangs up while B is getting the numbers announced. b. A hangs up after B gets the announcement, but before the parking time expires c. A waits, time expires, B is redialed, B answers, A and B are connected, after which, A hangs up. d. C picks up A while still in parking lot. Testing this throroughly involves acting all the permutations of I and II, in situations 1,2,3, and 4. Since I added a few more changes (ALL references to KEEPALIVE in the bridge code eliimated (I missed one earlier), I retested most of the above cases, and no crashes. H-extension weirdness. Current h-extension execution is not completely correct for several of the cases. For the case where A calls B, and A parks B, the 'h' exten is run on A's channel as soon as the park is accomplished. This is expected behavior. But when A calls B, and B parks A, this will be current behavior: After B parks A, B is hung up by the system, and the 'h' (hangup) exten gets run, but the channel mentioned will be a derivative of A's... Thus, if A is DAHDI/1, and B is DAHDI/2, the h-extension will be run on channel Parked/DAHDI/1-1<ZOMBIE>, and the start/answer/end info will be those relating to Channel A. And, in the case where A is reconnected to B after the park time expires, when both parties hang up after the joyful reunion, no h-exten will be run at all. In the case where C picks up A from the parking lot, when either A or C hang up, the h-exten will be run for the C channel. CDR's are a separate issue, and not addressed here. As to WHY this strange behavior occurs, the answer lies in the procedure followed to accomplish handing over the channel to the parking manager thread. This procedure is called masquerading. In the process, a duplicate copy of the channel is created, and most of the active data is given to the new copy. The original channel gets its name changed to XXX<ZOMBIE> and keeps the PBX information for the sake of the original thread (preserving its role as a call originator, if it had this role to begin with), while the new channel is without this info and becomes a call target (a "peer"). In this case, the parking lot manager thread is handed the new (masqueraded) channel. It will not run an h-exten on the channel if it hangs up while in the parking lot. The h exten will be run on the original channel instead, in the original thread, after the bridge completes. See bug 13820 for our intentions as to how to clean up the h exten behavior. Review: http://reviewboard.digium.com/r/29/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@166729 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-12-24 00:52:12 +00:00
ast_hangup(peer);
return -1;
} else {
/*! \todo XXX Play a message XXX */
if (ast_stream_and_wait(chan, "pbx-invalidpark", ""))
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
ast_verb(3, "Channel %s tried to talk to nonexistent parked call %d\n", chan->name, park);
res = -1;
}
return -1;
}
/*!
* \brief Add parking hints for all defined parking lots
* \param context
* \param start starting parkinglot number
* \param stop ending parkinglot number
*/
static void park_add_hints(char *context, int start, int stop)
{
int numext;
char device[AST_MAX_EXTENSION];
char exten[10];
for (numext = start; numext <= stop; numext++) {
snprintf(exten, sizeof(exten), "%d", numext);
snprintf(device, sizeof(device), "park:%s@%s", exten, context);
ast_add_extension(context, 1, exten, PRIORITY_HINT, NULL, NULL, device, NULL, NULL, registrar);
}
}
static int load_config(void)
{
int start = 0, end = 0;
int res;
int i;
struct ast_context *con = NULL;
struct ast_config *cfg = NULL;
struct ast_variable *var = NULL;
struct feature_group *fg = NULL;
struct ast_flags config_flags = { 0 };
char old_parking_ext[AST_MAX_EXTENSION];
char old_parking_con[AST_MAX_EXTENSION] = "";
char *ctg;
static const char *categories[] = {
/* Categories in features.conf that are not
* to be parsed as group categories
*/
"general",
"featuremap",
"applicationmap"
};
if (!ast_strlen_zero(parking_con)) {
strcpy(old_parking_ext, parking_ext);
strcpy(old_parking_con, parking_con);
}
/* Reset to defaults */
strcpy(parking_con, "parkedcalls");
strcpy(parking_con_dial, "park-dial");
strcpy(parking_ext, "700");
strcpy(pickup_ext, "*8");
strcpy(parkmohclass, "default");
courtesytone[0] = '\0';
strcpy(xfersound, "beep");
strcpy(xferfailsound, "pbx-invalid");
parking_start = 701;
parking_stop = 750;
parkfindnext = 0;
adsipark = 0;
comebacktoorigin = 1;
parkaddhints = 0;
parkedcalltransfers = 0;
parkedcallreparking = 0;
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
parkedcallrecording = 0;
parkedcallhangup = 0;
transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
atxferdropcall = DEFAULT_ATXFER_DROP_CALL;
atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
cfg = ast_config_load("features.conf", config_flags);
if (!cfg) {
ast_log(LOG_WARNING,"Could not load features.conf\n");
return 0;
}
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
if (!strcasecmp(var->name, "parkext")) {
ast_copy_string(parking_ext, var->value, sizeof(parking_ext));
} else if (!strcasecmp(var->name, "context")) {
ast_copy_string(parking_con, var->value, sizeof(parking_con));
} else if (!strcasecmp(var->name, "parkingtime")) {
if ((sscanf(var->value, "%30d", &parkingtime) != 1) || (parkingtime < 1)) {
ast_log(LOG_WARNING, "%s is not a valid parkingtime\n", var->value);
parkingtime = DEFAULT_PARK_TIME;
} else
parkingtime = parkingtime * 1000;
} else if (!strcasecmp(var->name, "parkpos")) {
if (sscanf(var->value, "%30d-%30d", &start, &end) != 2) {
ast_log(LOG_WARNING, "Format for parking positions is a-b, where a and b are numbers at line %d of features.conf\n", var->lineno);
} else {
parking_start = start;
parking_stop = end;
}
} else if (!strcasecmp(var->name, "findslot")) {
parkfindnext = (!strcasecmp(var->value, "next"));
} else if (!strcasecmp(var->name, "parkinghints")) {
parkaddhints = ast_true(var->value);
} else if (!strcasecmp(var->name, "parkedcalltransfers")) {
if (!strcasecmp(var->value, "both"))
parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
else if (!strcasecmp(var->value, "caller"))
parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
else if (!strcasecmp(var->value, "callee"))
parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
} else if (!strcasecmp(var->name, "parkedcallreparking")) {
if (!strcasecmp(var->value, "both"))
parkedcalltransfers = AST_FEATURE_FLAG_BYBOTH;
else if (!strcasecmp(var->value, "caller"))
parkedcalltransfers = AST_FEATURE_FLAG_BYCALLER;
else if (!strcasecmp(var->value, "callee"))
parkedcalltransfers = AST_FEATURE_FLAG_BYCALLEE;
Merged revisions 172580 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk ................ r172580 | twilson | 2009-01-30 15:29:12 -0600 (Fri, 30 Jan 2009) | 44 lines Merged revisions 172517 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r172517 | twilson | 2009-01-30 11:47:41 -0600 (Fri, 30 Jan 2009) | 37 lines Fix feature inheritance with builtin features When using builtin features like parking and transfers, the AST_FEATURE_* flags would not be set correctly for all instances when either performing a builtin attended transfer, or parking a call and getting the timeout callback. Also, there was no way on a per-call basis to specify what features someone should have on picking up a parked call (since that doesn't involve the Dial() command). There was a global option for setting whether or not all users who pickup a parked call should have AST_FEATURE_REDIRECT set, but nothing for DISCONNECT, AUTOMON, or PARKCALL. This patch: 1) adds the BRIDGE_FEATURES dialplan variable which can be set either in the dialplan or with setvar in channels that support it. This variable can be set to any combination of 't', 'k', 'w', and 'h' (case insensitive matching of the equivalent dial options), to set what features should be activated on this channel. The patch moves the setting of the features datastores into the bridging code instead of app_dial to help facilitate this. 2) adds global options parkedcallparking, parkedcallhangup, and parkedcallrecording to be similar to the parkedcalltransfers option for globally setting features. 3) has builtin_atxfer call builtin_parkcall if being transfered to the parking extension since tracking everything through multiple masquerades, etc. is difficult and error-prone 4) attempts to fix all cases of return calls from parking and completed builtin transfers not having the correct permissions (closes issue #14274) Reported by: aragon Patches: fix_feature_inheritence.diff.txt uploaded by otherwiseguy (license 396) Tested by: aragon, otherwiseguy Review http://reviewboard.digium.com/r/138/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@172635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-01-30 23:58:31 +00:00
} else if (!strcasecmp(var->name, "parkedcallhangup")) {
if (!strcasecmp(var->value, "both"))
parkedcallhangup = AST_FEATURE_FLAG_BYBOTH;
else if (!strcasecmp(var->value, "caller"))
parkedcallhangup = AST_FEATURE_FLAG_BYCALLER;
else if (!strcasecmp(var->value, "callee"))
parkedcallhangup = AST_FEATURE_FLAG_BYCALLEE;
} else if (!strcasecmp(var->name, "parkedcallrecording")) {
if (!strcasecmp(var->value, "both"))
parkedcallrecording = AST_FEATURE_FLAG_BYBOTH;
else if (!strcasecmp(var->value, "caller"))
parkedcallrecording = AST_FEATURE_FLAG_BYCALLER;
else if (!strcasecmp(var->value, "callee"))
parkedcallrecording = AST_FEATURE_FLAG_BYCALLEE;
} else if (!strcasecmp(var->name, "adsipark")) {
adsipark = ast_true(var->value);
} else if (!strcasecmp(var->name, "transferdigittimeout")) {
if ((sscanf(var->value, "%30d", &transferdigittimeout) != 1) || (transferdigittimeout < 1)) {
ast_log(LOG_WARNING, "%s is not a valid transferdigittimeout\n", var->value);
transferdigittimeout = DEFAULT_TRANSFER_DIGIT_TIMEOUT;
} else
transferdigittimeout = transferdigittimeout * 1000;
} else if (!strcasecmp(var->name, "featuredigittimeout")) {
if ((sscanf(var->value, "%30d", &featuredigittimeout) != 1) || (featuredigittimeout < 1)) {
ast_log(LOG_WARNING, "%s is not a valid featuredigittimeout\n", var->value);
featuredigittimeout = DEFAULT_FEATURE_DIGIT_TIMEOUT;
}
} else if (!strcasecmp(var->name, "atxfernoanswertimeout")) {
if ((sscanf(var->value, "%30d", &atxfernoanswertimeout) != 1) || (atxfernoanswertimeout < 1)) {
ast_log(LOG_WARNING, "%s is not a valid atxfernoanswertimeout\n", var->value);
atxfernoanswertimeout = DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER;
} else
atxfernoanswertimeout = atxfernoanswertimeout * 1000;
} else if (!strcasecmp(var->name, "atxferloopdelay")) {
if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
ast_log(LOG_WARNING, "%s is not a valid atxferloopdelay\n", var->value);
atxferloopdelay = DEFAULT_ATXFER_LOOP_DELAY;
} else
atxferloopdelay *= 1000;
} else if (!strcasecmp(var->name, "atxferdropcall")) {
atxferdropcall = ast_true(var->value);
} else if (!strcasecmp(var->name, "atxfercallbackretries")) {
if ((sscanf(var->value, "%30u", &atxferloopdelay) != 1)) {
ast_log(LOG_WARNING, "%s is not a valid atxfercallbackretries\n", var->value);
atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
}
} else if (!strcasecmp(var->name, "courtesytone")) {
ast_copy_string(courtesytone, var->value, sizeof(courtesytone));
} else if (!strcasecmp(var->name, "parkedplay")) {
if (!strcasecmp(var->value, "both"))
parkedplay = 2;
else if (!strcasecmp(var->value, "parked"))
parkedplay = 1;
else
parkedplay = 0;
} else if (!strcasecmp(var->name, "xfersound")) {
ast_copy_string(xfersound, var->value, sizeof(xfersound));
} else if (!strcasecmp(var->name, "xferfailsound")) {
ast_copy_string(xferfailsound, var->value, sizeof(xferfailsound));
} else if (!strcasecmp(var->name, "pickupexten")) {
ast_copy_string(pickup_ext, var->value, sizeof(pickup_ext));
} else if (!strcasecmp(var->name, "comebacktoorigin")) {
comebacktoorigin = ast_true(var->value);
} else if (!strcasecmp(var->name, "parkedmusicclass")) {
ast_copy_string(parkmohclass, var->value, sizeof(parkmohclass));
}
}
unmap_features();
for (var = ast_variable_browse(cfg, "featuremap"); var; var = var->next) {
if (remap_feature(var->name, var->value))
ast_log(LOG_NOTICE, "Unknown feature '%s'\n", var->name);
}
/* Map a key combination to an application*/
ast_unregister_features();
for (var = ast_variable_browse(cfg, "applicationmap"); var; var = var->next) {
char *tmp_val = ast_strdupa(var->value);
char *exten, *activateon, *activatedby, *app, *app_args, *moh_class;
struct ast_call_feature *feature;
/* strsep() sets the argument to NULL if match not found, and it
* is safe to use it with a NULL argument, so we don't check
* between calls.
*/
exten = strsep(&tmp_val,",");
activatedby = strsep(&tmp_val,",");
app = strsep(&tmp_val,",");
app_args = strsep(&tmp_val,",");
moh_class = strsep(&tmp_val,",");
activateon = strsep(&activatedby, "/");
/*! \todo XXX var_name or app_args ? */
if (ast_strlen_zero(app) || ast_strlen_zero(exten) || ast_strlen_zero(activateon) || ast_strlen_zero(var->name)) {
ast_log(LOG_NOTICE, "Please check the feature Mapping Syntax, either extension, name, or app aren't provided %s %s %s %s\n",
app, exten, activateon, var->name);
continue;
}
AST_RWLIST_RDLOCK(&feature_list);
if ((feature = find_dynamic_feature(var->name))) {
AST_RWLIST_UNLOCK(&feature_list);
ast_log(LOG_WARNING, "Dynamic Feature '%s' specified more than once!\n", var->name);
continue;
}
AST_RWLIST_UNLOCK(&feature_list);
if (!(feature = ast_calloc(1, sizeof(*feature))))
continue;
ast_copy_string(feature->sname, var->name, FEATURE_SNAME_LEN);
ast_copy_string(feature->app, app, FEATURE_APP_LEN);
ast_copy_string(feature->exten, exten, FEATURE_EXTEN_LEN);
if (app_args)
ast_copy_string(feature->app_args, app_args, FEATURE_APP_ARGS_LEN);
if (moh_class)
ast_copy_string(feature->moh_class, moh_class, FEATURE_MOH_LEN);
ast_copy_string(feature->exten, exten, sizeof(feature->exten));
feature->operation = feature_exec_app;
ast_set_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF);
/* Allow caller and calle to be specified for backwards compatability */
if (!strcasecmp(activateon, "self") || !strcasecmp(activateon, "caller"))
ast_set_flag(feature, AST_FEATURE_FLAG_ONSELF);
else if (!strcasecmp(activateon, "peer") || !strcasecmp(activateon, "callee"))
ast_set_flag(feature, AST_FEATURE_FLAG_ONPEER);
else {
ast_log(LOG_NOTICE, "Invalid 'ActivateOn' specification for feature '%s',"
" must be 'self', or 'peer'\n", var->name);
continue;
}
if (ast_strlen_zero(activatedby))
ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
else if (!strcasecmp(activatedby, "caller"))
ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLER);
else if (!strcasecmp(activatedby, "callee"))
ast_set_flag(feature, AST_FEATURE_FLAG_BYCALLEE);
else if (!strcasecmp(activatedby, "both"))
ast_set_flag(feature, AST_FEATURE_FLAG_BYBOTH);
else {
ast_log(LOG_NOTICE, "Invalid 'ActivatedBy' specification for feature '%s',"
" must be 'caller', or 'callee', or 'both'\n", var->name);
continue;
}
ast_register_feature(feature);
ast_verb(2, "Mapping Feature '%s' to app '%s(%s)' with code '%s'\n", var->name, app, app_args, exten);
}
ast_unregister_groups();
AST_RWLIST_WRLOCK(&feature_groups);
ctg = NULL;
while ((ctg = ast_category_browse(cfg, ctg))) {
for (i = 0; i < ARRAY_LEN(categories); i++) {
if (!strcasecmp(categories[i], ctg))
break;
}
if (i < ARRAY_LEN(categories))
continue;
if (!(fg = register_group(ctg)))
continue;
for (var = ast_variable_browse(cfg, ctg); var; var = var->next) {
struct ast_call_feature *feature;
AST_RWLIST_RDLOCK(&feature_list);
if (!(feature = find_dynamic_feature(var->name)) &&
!(feature = ast_find_call_feature(var->name))) {
AST_RWLIST_UNLOCK(&feature_list);
ast_log(LOG_WARNING, "Feature '%s' was not found.\n", var->name);
continue;
}
AST_RWLIST_UNLOCK(&feature_list);
register_group_feature(fg, var->value, feature);
}
}
AST_RWLIST_UNLOCK(&feature_groups);
ast_config_destroy(cfg);
/* Remove the old parking extension */
if (!ast_strlen_zero(old_parking_con) && (con = ast_context_find(old_parking_con))) {
if(ast_context_remove_extension2(con, old_parking_ext, 1, registrar, 0))
notify_metermaids(old_parking_ext, old_parking_con, AST_DEVICE_NOT_INUSE);
ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
}
Merged revisions 130145 via svnmerge from https://origsvn.digium.com/svn/asterisk/trunk Merging this rev from trunk to 1.6.0 was not simple. Why? Because we've enhanced trunk to do a [fast] merge-and-delete operation which also solved problems with contexts having entries from different registrars. Fast as in the amount of time the contexts are locked down. That *is* fast, but traversing the entire dialplan looking for priorities to delete takes more time overall. This particular fix involved pulling in those enhancements from trunk, along with all the various fixes and refinements made along the way. Merging all this from trunk into 1.6 involved: a. mergetrunk6 in the stuff from 130145; b. revert all but the prop changes c. catalog all revisions to pbx.c since 1.6.0 was forked (at rev 105596). d. catalog all revisions to pbx.c in trunk since 1.6.0 was forked, making special note of all revs that were not merged into 1.6.0. e. study each rev in trunk not applied to 1.6.0, and determine if it was involved in the merge_and_delete enhancements in trunk. 25 commits were done in 1.6.0, all but one (106306) was a merge from trunk. Trunk had 22 additional changes, of which 7 were involved in the merge_and_delete enhancements: 106757 108894 109169 116461 123358 130145 130297 f. Go to trunk and collect patches, one by one, of the changes made by each rev across the entire source tree, using svn diff -c <num> > pfile g. Apply each patch in order to 1.6.0, and resolve all failures and compilation problems before proceding to the next patch. h. test the stuff. i. profit! ........ r130145 | murf | 2008-07-11 12:24:31 -0600 (Fri, 11 Jul 2008) | 40 lines (closes issue #13041) Reported by: eliel Tested by: murf (closes issue #12960) Reported by: mnicholson In this 'omnibus' fix, I **think** I solved both the problem in 13041, where unloading pbx_ael.so caused crashes, or incomplete removal of previous registrar'ed entries. And I added code to completely remove all includes, switches, and ignorepats that had a matching registrar entry, which should appease 12960. I also added a lot of seemingly useless brackets around single statement if's, which helped debug so much that I'm leaving them there. I added a routine to check the correlation between the extension tree lists and the hashtab tables. It can be amazingly helpful when you have lots of dialplan stuff, and need to narrow down where a problem is occurring. It's ifdef'd out by default. I cleaned up the code around the new CIDmatch code. It was leaving hanging extens with bad ptrs, getting confused over which objects to remove, etc. I tightened up the code and changed the call to remove_exten in the merge_and_delete code. I added more conditions to check for empty context worthy of deletion. It's not empty if there are any includes, switches, or ignorepats present. If I've missed anything, please re-open this bug, and be prepared to supply example dialplan code. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@130946 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-07-15 13:14:07 +00:00
if (!(con = ast_context_find_or_create(NULL, NULL, parking_con, registrar))) {
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
return -1;
}
res = ast_add_extension2(con, 1, ast_parking_ext(), 1, NULL, NULL, parkcall, NULL, NULL, registrar);
if (parkaddhints)
park_add_hints(parking_con, parking_start, parking_stop);
if (!res)
notify_metermaids(ast_parking_ext(), parking_con, AST_DEVICE_INUSE);
return res;
}
/*!
* \brief CLI command to list configured features
* \param e
* \param cmd
* \param a
*
* \retval CLI_SUCCESS on success.
* \retval NULL when tab completion is used.
*/
static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int i;
struct ast_call_feature *feature;
#define HFS_FORMAT "%-25s %-7s %-7s\n"
switch (cmd) {
case CLI_INIT:
e->command = "features show";
e->usage =
"Usage: features show\n"
" Lists configured features\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
ast_cli(a->fd, HFS_FORMAT, "Pickup", "*8", ast_pickup_ext()); /* default hardcoded above, so we'll hardcode it here */
ast_rwlock_rdlock(&features_lock);
for (i = 0; i < FEATURES_COUNT; i++)
ast_cli(a->fd, HFS_FORMAT, builtin_features[i].fname, builtin_features[i].default_exten, builtin_features[i].exten);
ast_rwlock_unlock(&features_lock);
ast_cli(a->fd, "\n");
ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
if (AST_RWLIST_EMPTY(&feature_list)) {
ast_cli(a->fd, "(none)\n");
} else {
AST_RWLIST_RDLOCK(&feature_list);
AST_RWLIST_TRAVERSE(&feature_list, feature, feature_entry) {
ast_cli(a->fd, HFS_FORMAT, feature->sname, "no def", feature->exten);
}
AST_RWLIST_UNLOCK(&feature_list);
}
ast_cli(a->fd, "\nCall parking\n");
ast_cli(a->fd, "------------\n");
ast_cli(a->fd,"%-20s: %s\n", "Parking extension", parking_ext);
ast_cli(a->fd,"%-20s: %s\n", "Parking context", parking_con);
ast_cli(a->fd,"%-20s: %d-%d\n", "Parked call extensions", parking_start, parking_stop);
ast_cli(a->fd,"\n");
return CLI_SUCCESS;
}
int ast_features_reload(void)
{
load_config();
return RESULT_SUCCESS;
}
static char *handle_features_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
switch (cmd) {
case CLI_INIT:
e->command = "features reload";
e->usage =
"Usage: features reload\n"
" Reloads configured call features from features.conf\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
load_config();
return CLI_SUCCESS;
}
static char mandescr_bridge[] =
"Description: Bridge together two channels already in the PBX\n"
"Variables: ( Headers marked with * are required )\n"
" *Channel1: Channel to Bridge to Channel2\n"
" *Channel2: Channel to Bridge to Channel1\n"
" Tone: (Yes|No) Play courtesy tone to Channel 2\n"
"\n";
/*!
* \brief Actual bridge
* \param chan
* \param tmpchan
*
* Stop hold music, lock both channels, masq channels,
* after bridge return channel to next priority.
*/
static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
{
ast_moh_stop(chan);
ast_channel_lock(chan);
ast_setstate(tmpchan, chan->_state);
tmpchan->readformat = chan->readformat;
tmpchan->writeformat = chan->writeformat;
ast_channel_masquerade(tmpchan, chan);
ast_channel_lock(tmpchan);
ast_do_masquerade(tmpchan);
/* when returning from bridge, the channel will continue at the next priority */
ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
ast_channel_unlock(tmpchan);
ast_channel_unlock(chan);
}
/*!
* \brief Bridge channels together
* \param s
* \param m
*
* Make 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.
*
* \retval 0 on success or on incorrect use.
* \retval 1 on failure to bridge channels.
*/
static int action_bridge(struct mansession *s, const struct message *m)
{
const char *channela = astman_get_header(m, "Channel1");
const char *channelb = astman_get_header(m, "Channel2");
const char *playtone = astman_get_header(m, "Tone");
struct ast_channel *chana = NULL, *chanb = NULL;
struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
struct ast_bridge_thread_obj *tobj = NULL;
/* make sure valid channels were specified */
if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
astman_send_error(s, m, "Missing channel parameter in request");
return 0;
}
/* The same code must be executed for chana and chanb. To avoid a
* theoretical deadlock, this code is separated so both chana and chanb will
* not hold locks at the same time. */
/* Start with chana */
chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
/* send errors if any of the channels could not be found/locked */
if (!chana) {
char buf[256];
snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
astman_send_error(s, m, buf);
return 0;
}
/* Answer the channels if needed */
if (chana->_state != AST_STATE_UP)
ast_answer(chana);
/* create the placeholder channels and grab the other channels */
if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, "Bridge/%s", chana->name))) {
astman_send_error(s, m, "Unable to create temporary channel!");
ast_channel_unlock(chana);
return 1;
}
do_bridge_masquerade(chana, tmpchana);
ast_channel_unlock(chana);
chana = NULL;
/* now do chanb */
chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
/* send errors if any of the channels could not be found/locked */
if (!chanb) {
char buf[256];
snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
ast_hangup(tmpchana);
astman_send_error(s, m, buf);
return 0;
}
/* Answer the channels if needed */
if (chanb->_state != AST_STATE_UP)
ast_answer(chanb);
/* create the placeholder channels and grab the other channels */
if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, "Bridge/%s", chanb->name))) {
astman_send_error(s, m, "Unable to create temporary channels!");
ast_hangup(tmpchana);
ast_channel_unlock(chanb);
return 1;
}
do_bridge_masquerade(chanb, tmpchanb);
ast_channel_unlock(chanb);
chanb = NULL;
/* make the channels compatible, send error if we fail doing so */
if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
astman_send_error(s, m, "Could not make channels compatible for manager bridge");
ast_hangup(tmpchana);
ast_hangup(tmpchanb);
return 1;
}
/* setup the bridge thread object and start the bridge */
if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
astman_send_error(s, m, "Unable to spawn a new bridge thread");
ast_hangup(tmpchana);
ast_hangup(tmpchanb);
return 1;
}
tobj->chan = tmpchana;
tobj->peer = tmpchanb;
tobj->return_to_pbx = 1;
if (ast_true(playtone)) {
if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, tmpchanb->language)) {
if (ast_waitstream(tmpchanb, "") < 0)
ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", tmpchanb->name);
}
}
ast_bridge_call_thread_launch(tobj);
astman_send_ack(s, m, "Launched bridge thread with success");
return 0;
}
/*!
* \brief CLI command to list parked calls
* \param e
* \param cmd
* \param a
*
* Check right usage, lock parking lot, display parked calls, unlock parking lot list.
* \retval CLI_SUCCESS on success.
* \retval CLI_SHOWUSAGE on incorrect number of arguments.
* \retval NULL when tab completion is used.
*/
static char *handle_parkedcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct parkeduser *cur;
int numparked = 0;
switch (cmd) {
case CLI_INIT:
e->command = "parkedcalls show";
e->usage =
"Usage: parkedcalls show\n"
" List currently parked calls\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc > e->args)
return CLI_SHOWUSAGE;
ast_cli(a->fd, "%4s %25s (%-15s %-12s %-4s) %-6s \n", "Num", "Channel"
, "Context", "Extension", "Pri", "Timeout");
AST_LIST_LOCK(&parkinglot);
AST_LIST_TRAVERSE(&parkinglot, cur, list) {
ast_cli(a->fd, "%-10.10s %25s (%-15s %-12s %-4d) %6lds\n"
,cur->parkingexten, cur->chan->name, cur->context, cur->exten
,cur->priority, cur->start.tv_sec + (cur->parkingtime/1000) - time(NULL));
numparked++;
}
AST_LIST_UNLOCK(&parkinglot);
ast_cli(a->fd, "%d parked call%s.\n", numparked, ESS(numparked));
return CLI_SUCCESS;
}
static char *handle_parkedcalls_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *res = handle_parkedcalls(e, cmd, a);
if (cmd == CLI_INIT)
e->command = "show parkedcalls";
return res;
}
static struct ast_cli_entry cli_show_parkedcalls_deprecated = AST_CLI_DEFINE(handle_parkedcalls_deprecated, "List currently parked calls.");
static struct ast_cli_entry cli_features[] = {
AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
AST_CLI_DEFINE(handle_features_reload, "Reloads configured features"),
AST_CLI_DEFINE(handle_parkedcalls, "List currently parked calls", .deprecate_cmd = &cli_show_parkedcalls_deprecated),
};
/*!
* \brief Dump parking lot status
* \param s
* \param m
*
* Lock parking lot, iterate list and append parked calls status, unlock parking lot.
* \return Always RESULT_SUCCESS
*/
static int manager_parking_status(struct mansession *s, const struct message *m)
{
struct parkeduser *cur;
const char *id = astman_get_header(m, "ActionID");
char idText[256] = "";
if (!ast_strlen_zero(id))
snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
astman_send_ack(s, m, "Parked calls will follow");
AST_LIST_LOCK(&parkinglot);
AST_LIST_TRAVERSE(&parkinglot, cur, list) {
astman_append(s, "Event: ParkedCall\r\n"
"Exten: %d\r\n"
"Channel: %s\r\n"
"From: %s\r\n"
"Timeout: %ld\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
"%s"
"\r\n",
cur->parkingnum, cur->chan->name, cur->peername,
(long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
S_OR(cur->chan->cid.cid_num, ""), /* XXX in other places it is <unknown> */
S_OR(cur->chan->cid.cid_name, ""),
idText);
}
astman_append(s,
"Event: ParkedCallsComplete\r\n"
"%s"
"\r\n",idText);
AST_LIST_UNLOCK(&parkinglot);
return RESULT_SUCCESS;
}
static char mandescr_park[] =
"Description: Park a channel.\n"
"Variables: (Names marked with * are required)\n"
" *Channel: Channel name to park\n"
" *Channel2: Channel to announce park info to (and return to if timeout)\n"
" Timeout: Number of milliseconds to wait before callback.\n";
/*!
* \brief Create manager event for parked calls
* \param s
* \param m
*
* Get channels involved in park, create event.
* \return Always 0
*/
static int manager_park(struct mansession *s, const struct message *m)
{
const char *channel = astman_get_header(m, "Channel");
const char *channel2 = astman_get_header(m, "Channel2");
const char *timeout = astman_get_header(m, "Timeout");
char buf[BUFSIZ];
int to = 0;
int res = 0;
int parkExt = 0;
struct ast_channel *ch1, *ch2;
if (ast_strlen_zero(channel)) {
astman_send_error(s, m, "Channel not specified");
return 0;
}
if (ast_strlen_zero(channel2)) {
astman_send_error(s, m, "Channel2 not specified");
return 0;
}
ch1 = ast_get_channel_by_name_locked(channel);
if (!ch1) {
snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
astman_send_error(s, m, buf);
return 0;
}
ch2 = ast_get_channel_by_name_locked(channel2);
if (!ch2) {
snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
astman_send_error(s, m, buf);
ast_channel_unlock(ch1);
return 0;
}
if (!ast_strlen_zero(timeout)) {
sscanf(timeout, "%30d", &to);
}
res = ast_masq_park_call(ch1, ch2, to, &parkExt);
if (!res) {
ast_softhangup(ch2, AST_SOFTHANGUP_EXPLICIT);
astman_send_ack(s, m, "Park successful");
} else {
astman_send_error(s, m, "Park failure");
}
ast_channel_unlock(ch1);
ast_channel_unlock(ch2);
return 0;
}
/*!
* \brief Pickup a call
* \param chan channel that initiated pickup.
*
* Walk list of channels, checking it is not itself, channel is pbx one,
* check that the callgroup for both channels are the same and the channel is ringing.
* Answer calling channel, flag channel as answered on queue, masq channels together.
*/
int ast_pickup_call(struct ast_channel *chan)
{
struct ast_channel *cur = NULL;
int res = -1;
while ((cur = ast_channel_walk_locked(cur)) != NULL) {
if (!cur->pbx &&
(cur != chan) &&
(chan->pickupgroup & cur->callgroup) &&
((cur->_state == AST_STATE_RINGING) ||
(cur->_state == AST_STATE_RING))) {
break;
}
ast_channel_unlock(cur);
}
if (cur) {
ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
res = ast_answer(chan);
if (res)
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
res = ast_queue_control(chan, AST_CONTROL_ANSWER);
if (res)
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
res = ast_channel_masquerade(cur, chan);
if (res)
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
ast_channel_unlock(cur);
} else {
ast_debug(1, "No call pickup possible...\n");
}
return res;
}
static char *app_bridge = "Bridge";
static char *bridge_synopsis = "Bridge two channels";
static char *bridge_descrip =
"Usage: Bridge(channel[,options])\n"
" Allows the ability to bridge two channels via the dialplan.\n"
"The current channel is bridged to the specified 'channel'.\n"
" Options:\n"
" p - Play a courtesy tone to 'channel'.\n"
"This application sets the following channel variable upon completion:\n"
" BRIDGERESULT The result of the bridge attempt as a text string, one of\n"
" SUCCESS | FAILURE | LOOP | NONEXISTENT | INCOMPATIBLE\n";
enum {
BRIDGE_OPT_PLAYTONE = (1 << 0),
};
AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE)
END_OPTIONS );
/*!
* \brief Bridge channels
* \param chan
* \param data channel 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 transfered party hangs up return to PBX extension.
*/
static int bridge_exec(struct ast_channel *chan, void *data)
{
struct ast_channel *current_dest_chan, *final_dest_chan;
char *tmp_data = NULL;
struct ast_flags opts = { 0, };
struct ast_bridge_config bconfig = { { 0, }, };
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(dest_chan);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Bridge require at least 1 argument specifying the other end of the bridge\n");
return -1;
}
tmp_data = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, tmp_data);
if (!ast_strlen_zero(args.options))
ast_app_parse_options(bridge_exec_options, &opts, NULL, args.options);
/* avoid bridge with ourselves */
if (!strncmp(chan->name, args.dest_chan,
strlen(chan->name) < strlen(args.dest_chan) ?
strlen(chan->name) : strlen(args.dest_chan))) {
ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
manager_event(EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: Unable to bridge channel to itself\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n",
chan->name, args.dest_chan);
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
return 0;
}
/* make sure we have a valid end point */
if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
strlen(args.dest_chan)))) {
ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
"cannot get its lock\n", args.dest_chan);
manager_event(EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: Cannot grab end point\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, args.dest_chan);
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
return 0;
}
/* answer the channel if needed */
if (current_dest_chan->_state != AST_STATE_UP)
ast_answer(current_dest_chan);
/* try to allocate a place holder where current_dest_chan will be placed */
if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, "Bridge/%s", current_dest_chan->name))) {
ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
manager_event(EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: cannot create placeholder\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, args.dest_chan);
}
do_bridge_masquerade(current_dest_chan, final_dest_chan);
ast_channel_unlock(current_dest_chan);
/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
/* try to make compatible, send error if we fail */
if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
manager_event(EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: Could not make channels compatible for bridge\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, final_dest_chan->name);
ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
return 0;
}
/* Report that the bridge will be successfull */
manager_event(EVENT_FLAG_CALL, "BridgeExec",
"Response: Success\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, final_dest_chan->name);
/* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
if (!ast_streamfile(final_dest_chan, xfersound, final_dest_chan->language)) {
if (ast_waitstream(final_dest_chan, "") < 0)
ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
}
}
/* do the bridge */
ast_bridge_call(chan, final_dest_chan, &bconfig);
/* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
if (!ast_check_hangup(final_dest_chan)) {
ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
final_dest_chan->context, final_dest_chan->exten,
final_dest_chan->priority, final_dest_chan->name);
if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", final_dest_chan->name);
ast_hangup(final_dest_chan);
} else
ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
} else {
ast_debug(1, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
ast_hangup(final_dest_chan);
}
return 0;
}
int ast_features_init(void)
{
int res;
ast_register_application2(app_bridge, bridge_exec, bridge_synopsis, bridge_descrip, NULL);
memset(parking_ext, 0, sizeof(parking_ext));
memset(parking_con, 0, sizeof(parking_con));
if ((res = load_config()))
return res;
ast_cli_register_multiple(cli_features, sizeof(cli_features) / sizeof(struct ast_cli_entry));
ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
res = ast_register_application2(parkedcall, park_exec, synopsis, descrip, NULL);
if (!res)
res = ast_register_application2(parkcall, park_call_exec, synopsis2, descrip2, NULL);
if (!res) {
ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls");
ast_manager_register2("Park", EVENT_FLAG_CALL, manager_park,
"Park a channel", mandescr_park);
ast_manager_register2("Bridge", EVENT_FLAG_CALL, action_bridge, "Bridge two channels already in the PBX", mandescr_bridge);
}
res |= ast_devstate_prov_add("Park", metermaidstate);
return res;
}