Various parking improvements.

* Adds per-parking lot options comebackcontext and comebackdialtime
* Makes comebacktoorigin settable per parking lot
* Sets a PARKER channel variable when comebacktoorigin is disabled

(closes issue ASTERISK-16643)
Reported by: Mitch Sharp (bluecrow76)
Patches:
asterisk-1.6.2.17.2-park-features-comebackcontext-consolidated-v3.diff by Mitch Sharp (bluecrow76) license 5231
with updates by me.

Review: https://reviewboard.asterisk.org/r/1674
Review: https://reviewboard.asterisk.org/r/963
Reviewed by Richard Mudgett



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@351913 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Michelson
2012-01-20 20:47:42 +00:00
parent b98a25ef93
commit 778fa4abaf
4 changed files with 89 additions and 14 deletions

View File

@@ -74,6 +74,14 @@ Applications
manually specify timezone and format) There are other beneftis eg. format can manually specify timezone and format) There are other beneftis eg. format can
now be used without specifying time zone as well. now be used without specifying time zone as well.
Parking
------------
* New per parking lot options: comebackcontext and comebackdialtime. See
configs/features.conf.sample for more details.
* Channel variable PARKER is now set when comebacktoorigin is disabled in
a parking lot.
CDR postgresql driver changes CDR postgresql driver changes
----------------------------- -----------------------------
* Added command "cdr show pgsql status" to check connection status * Added command "cdr show pgsql status" to check connection status

View File

@@ -22,6 +22,10 @@
From 10 to 11: From 10 to 11:
Parking:
- The comebacktoorigin setting must now be set per parking lot. The setting in
the general section will not be applied automatically to each parking lot.
Dialplan Functions: Dialplan Functions:
- MAILBOX_EXISTS has been deprecated. Use VM_INFO with the 'exists' parameter - MAILBOX_EXISTS has been deprecated. Use VM_INFO with the 'exists' parameter
instead. instead.

View File

@@ -19,18 +19,22 @@ context => parkedcalls ; Which context parked calls are in (default par
;comebacktoorigin = yes ; Setting this option configures the behavior of call parking when the ;comebacktoorigin = yes ; Setting this option configures the behavior of call parking when the
; parked call times out (See the parkingtime option). The default value is 'yes'. ; parked call times out (See the parkingtime option). The default value is 'yes'.
; Operates on all parking lots. ; Set per parking lot.
; ;
; 'yes' - When the parked call times out, attempt to send the call back to the peer ; 'yes' - When the parked call times out, attempt to send the call back to the peer
; that parked this call. This is done by saving off the name of the channel ; that parked this call. This is done by saving off the name of the channel
; that parked the call. ; that parked the call. The call will return to the context 'park-dial' and
; an extension created based on the name of the channel that originally parked
; the call. This extension will be created automatically to do a Dial() to the
; device that originally parked the call for comebacktodialtime seconds. If the
; call is not answered, the call will proceed to 'park-dial,t,1'.
; ;
; 'no' - This option is useful for performing custom dialplan functionality prior to ; 'no' - This option is useful for performing custom dialplan functionality prior to
; sending the call back to the extension that initially parked the call, or to ; sending the call back to the extension that initially parked the call, or to
; an entirely different destination. ; an entirely different destination.
; ;
; When the parked call times out, send it back to the dialplan. The location ; When the parked call times out, send it back to the dialplan. The location
; will be the 'parkedcallstimeout' context. The extension will be built from ; will be defined by the comebackcontext option. The extension will be built from
; the saved channel name that parked the call. For example, if a SIP peer named ; the saved channel name that parked the call. For example, if a SIP peer named
; '0004F2040001' parked this call, the extension will be 'SIP_0004F2040001'. ; '0004F2040001' parked this call, the extension will be 'SIP_0004F2040001'.
; (Note that an underscore is used here because the '/' character has a special ; (Note that an underscore is used here because the '/' character has a special
@@ -46,6 +50,18 @@ context => parkedcalls ; Which context parked calls are in (default par
; During the timeout procedure, the following variables are set ; During the timeout procedure, the following variables are set
; PARKINGSLOT - extension that the call was parked in prior to timing out ; PARKINGSLOT - extension that the call was parked in prior to timing out
; PARKEDLOT - name of the lot that the call was parked in prior to timing out ; PARKEDLOT - name of the lot that the call was parked in prior to timing out
; PARKER - name of the device that parked the call
;comebackdialtime = 30 ; When a parked call times out, this is the number of seconds to dial the device that
; originally parked the call. It is also available as a channel variable COMEBACKDIALTIME
; after a parked call has timed out.
; The default value is 30 seconds.
; Set per parking lot.
;comebackcontext = parkedcallstimeout
; The context a timed out call will return to if comebcktoorigin=no.
; The default value is 'parkedcallstimeout'.
; Set per parking lot.
;courtesytone = beep ; Sound file to play to when someone picks up a parked call ;courtesytone = beep ; Sound file to play to when someone picks up a parked call
; and also when the Touch Monitor is activated/deactivated. ; and also when the Touch Monitor is activated/deactivated.
@@ -113,6 +129,10 @@ context => parkedcalls ; Which context parked calls are in (default par
;parkext => 799 ;parkext => 799
;parkpos => 800-850 ;parkpos => 800-850
;findslot => next ;findslot => next
;comebacktoorigin = no
;comebackdialtime = 90
;comebackcontext = edvinapark-timeout ; Make sure you create the context!
;parkedmusicclass = edvina
; Note that the DTMF features listed below only work when two channels have answered and are bridged together. ; Note that the DTMF features listed below only work when two channels have answered and are bridged together.
; They can not be used while the remote party is ringing or in progress. If you require this feature you can use ; They can not be used while the remote party is ringing or in progress. If you require this feature you can use

View File

@@ -388,6 +388,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define DEFAULT_ATXFER_DROP_CALL 0 /*!< Do not drop call. */ #define DEFAULT_ATXFER_DROP_CALL 0 /*!< Do not drop call. */
#define DEFAULT_ATXFER_LOOP_DELAY 10000 /*!< ms */ #define DEFAULT_ATXFER_LOOP_DELAY 10000 /*!< ms */
#define DEFAULT_ATXFER_CALLBACK_RETRIES 2 #define DEFAULT_ATXFER_CALLBACK_RETRIES 2
#define DEFAULT_COMEBACK_CONTEXT "parkedcallstimeout"
#define DEFAULT_COMEBACK_TO_ORIGIN 1
#define DEFAULT_COMEBACK_DIAL_TIME 30
#define AST_MAX_WATCHERS 256 #define AST_MAX_WATCHERS 256
#define MAX_DIAL_FEATURE_OPTIONS 30 #define MAX_DIAL_FEATURE_OPTIONS 30
@@ -494,7 +497,9 @@ struct parkinglot_cfg {
/*! Extension to park calls in this parking lot. */ /*! Extension to park calls in this parking lot. */
char parkext[AST_MAX_EXTENSION]; char parkext[AST_MAX_EXTENSION];
/*! Context for which parking is made accessible */ /*! Context for which parking is made accessible */
char parking_con[AST_MAX_EXTENSION]; char parking_con[AST_MAX_CONTEXT];
/*! Context that timed-out parked calls are called back on when comebacktoorigin=no */
char comebackcontext[AST_MAX_CONTEXT];
/*! First available extension for parking */ /*! First available extension for parking */
int parking_start; int parking_start;
/*! Last available extension for parking */ /*! Last available extension for parking */
@@ -542,6 +547,8 @@ struct parkinglot_cfg {
*/ */
int parkedcallrecording; int parkedcallrecording;
/*! Time in seconds to dial the device that parked a timedout parked call */
unsigned int comebackdialtime;
/*! TRUE if findslot is set to next */ /*! TRUE if findslot is set to next */
unsigned int parkfindnext:1; unsigned int parkfindnext:1;
/*! TRUE if the parking lot is exclusively accessed by parkext */ /*! TRUE if the parking lot is exclusively accessed by parkext */
@@ -550,6 +557,8 @@ struct parkinglot_cfg {
unsigned int parkaddhints:1; unsigned int parkaddhints:1;
/*! TRUE if configuration is invalid and the parking lot should not be used. */ /*! TRUE if configuration is invalid and the parking lot should not be used. */
unsigned int is_invalid:1; unsigned int is_invalid:1;
/*! TRUE if a timed out parked call goes back to the parker */
unsigned int comebacktoorigin:1;
}; };
/*! \brief Structure for parking lots which are put in a container. */ /*! \brief Structure for parking lots which are put in a container. */
@@ -609,7 +618,6 @@ static int adsipark;
static int transferdigittimeout; static int transferdigittimeout;
static int featuredigittimeout; static int featuredigittimeout;
static int comebacktoorigin = 1;
static int atxfernoanswertimeout; static int atxfernoanswertimeout;
static unsigned int atxferdropcall; static unsigned int atxferdropcall;
@@ -4600,6 +4608,7 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds,
parking_con_dial); parking_con_dial);
} else { } else {
char returnexten[AST_MAX_EXTENSION]; char returnexten[AST_MAX_EXTENSION];
char comebackdialtime[AST_MAX_EXTENSION];
struct ast_datastore *features_datastore; struct ast_datastore *features_datastore;
struct ast_dial_features *dialfeatures; struct ast_dial_features *dialfeatures;
@@ -4613,16 +4622,24 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds,
if (features_datastore && (dialfeatures = features_datastore->data)) { if (features_datastore && (dialfeatures = features_datastore->data)) {
char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,}; char buf[MAX_DIAL_FEATURE_OPTIONS] = {0,};
snprintf(returnexten, sizeof(returnexten), "%s,30,%s", peername, snprintf(returnexten, sizeof(returnexten), "%s,%u,%s", peername,
pu->parkinglot->cfg.comebackdialtime,
callback_dialoptions(&(dialfeatures->features_callee), callback_dialoptions(&(dialfeatures->features_callee),
&(dialfeatures->features_caller), buf, sizeof(buf))); &(dialfeatures->features_caller), buf, sizeof(buf)));
} else { /* Existing default */ } else { /* Existing default */
ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n", ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
ast_channel_name(chan)); ast_channel_name(chan));
snprintf(returnexten, sizeof(returnexten), "%s,30,t", peername); snprintf(returnexten, sizeof(returnexten), "%s,%u,t", peername,
pu->parkinglot->cfg.comebackdialtime);
} }
ast_channel_unlock(chan); ast_channel_unlock(chan);
snprintf(comebackdialtime, sizeof(comebackdialtime), "%u",
pu->parkinglot->cfg.comebackdialtime);
pbx_builtin_setvar_helper(chan, "COMEBACKDIALTIME", comebackdialtime);
pbx_builtin_setvar_helper(chan, "PARKER", peername);
if (ast_add_extension(parking_con_dial, 1, peername_flat, 1, NULL, NULL, if (ast_add_extension(parking_con_dial, 1, peername_flat, 1, NULL, NULL,
"Dial", ast_strdup(returnexten), ast_free_ptr, registrar)) { "Dial", ast_strdup(returnexten), ast_free_ptr, registrar)) {
ast_log(LOG_ERROR, ast_log(LOG_ERROR,
@@ -4636,7 +4653,7 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds,
* those arguments. * those arguments.
*/ */
set_c_e_p(chan, pu->context, pu->exten, pu->priority); set_c_e_p(chan, pu->context, pu->exten, pu->priority);
} else if (comebacktoorigin) { } else if (pu->parkinglot->cfg.comebacktoorigin) {
set_c_e_p(chan, parking_con_dial, peername_flat, 1); set_c_e_p(chan, parking_con_dial, peername_flat, 1);
} else { } else {
char parkingslot[AST_MAX_EXTENSION]; char parkingslot[AST_MAX_EXTENSION];
@@ -4644,7 +4661,7 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds,
snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum); snprintf(parkingslot, sizeof(parkingslot), "%d", pu->parkingnum);
pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot); pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
pbx_builtin_setvar_helper(chan, "PARKEDLOT", pu->parkinglot->name); pbx_builtin_setvar_helper(chan, "PARKEDLOT", pu->parkinglot->name);
set_c_e_p(chan, "parkedcallstimeout", peername_flat, 1); set_c_e_p(chan, pu->parkinglot->cfg.comebackcontext, peername_flat, 1);
} }
} else { } else {
/* /*
@@ -5331,12 +5348,18 @@ static const struct parkinglot_cfg parkinglot_cfg_default_default = {
.parking_start = 701, .parking_start = 701,
.parking_stop = 750, .parking_stop = 750,
.parkingtime = DEFAULT_PARK_TIME, .parkingtime = DEFAULT_PARK_TIME,
.comebackdialtime = DEFAULT_COMEBACK_DIAL_TIME,
.comebackcontext = DEFAULT_COMEBACK_CONTEXT,
.comebacktoorigin = DEFAULT_COMEBACK_TO_ORIGIN,
}; };
/*! Default configuration for normal parking lots. */ /*! Default configuration for normal parking lots. */
static const struct parkinglot_cfg parkinglot_cfg_default = { static const struct parkinglot_cfg parkinglot_cfg_default = {
.parkext = DEFAULT_PARK_EXTENSION, .parkext = DEFAULT_PARK_EXTENSION,
.parkingtime = DEFAULT_PARK_TIME, .parkingtime = DEFAULT_PARK_TIME,
.comebackdialtime = DEFAULT_COMEBACK_DIAL_TIME,
.comebackcontext = DEFAULT_COMEBACK_CONTEXT,
.comebacktoorigin = DEFAULT_COMEBACK_TO_ORIGIN,
}; };
/*! /*!
@@ -5423,6 +5446,16 @@ static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cf
parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var); parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallhangup, var);
} else if (!strcasecmp(var->name, "parkedcallrecording")) { } else if (!strcasecmp(var->name, "parkedcallrecording")) {
parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var); parkinglot_feature_flag_cfg(pl_name, &cfg->parkedcallrecording, var);
} else if (!strcasecmp(var->name, "comebackcontext")) {
ast_copy_string(cfg->comebackcontext, var->value, sizeof(cfg->comebackcontext));
} else if (!strcasecmp(var->name, "comebacktoorigin")) {
cfg->comebacktoorigin = ast_true(var->value);
} else if (!strcasecmp(var->name, "comebackdialtime")) {
if ((sscanf(var->value, "%30u", &cfg->comebackdialtime) != 1)
|| (cfg->comebackdialtime < 1)) {
ast_log(LOG_WARNING, "%s is not a valid comebackdialtime\n", var->value);
cfg->parkingtime = DEFAULT_COMEBACK_DIAL_TIME;
}
} }
var = var->next; var = var->next;
} }
@@ -5440,6 +5473,12 @@ static int parkinglot_config_read(const char *pl_name, struct parkinglot_cfg *cf
ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name); ast_log(LOG_WARNING, "Parking lot %s needs parkpos\n", pl_name);
error = -1; error = -1;
} }
if (!cfg->comebacktoorigin && ast_strlen_zero(cfg->comebackcontext)) {
ast_log(LOG_WARNING, "Parking lot %s has comebacktoorigin set false"
"but has no comebackcontext.\n",
pl_name);
error = -1;
}
if (error) { if (error) {
cfg->is_invalid = 1; cfg->is_invalid = 1;
} }
@@ -5718,7 +5757,6 @@ static int process_config(struct ast_config *cfg)
atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES; atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
/* Set global call parking defaults. */ /* Set global call parking defaults. */
comebacktoorigin = 1;
courtesytone[0] = '\0'; courtesytone[0] = '\0';
parkedplay = 0; parkedplay = 0;
adsipark = 0; adsipark = 0;
@@ -5784,8 +5822,6 @@ static int process_config(struct ast_config *cfg)
ast_copy_string(pickupsound, var->value, sizeof(pickupsound)); ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
} else if (!strcasecmp(var->name, "pickupfailsound")) { } else if (!strcasecmp(var->name, "pickupfailsound")) {
ast_copy_string(pickupfailsound, var->value, sizeof(pickupfailsound)); ast_copy_string(pickupfailsound, var->value, sizeof(pickupfailsound));
} else if (!strcasecmp(var->name, "comebacktoorigin")) {
comebacktoorigin = ast_true(var->value);
} }
} }
@@ -6688,6 +6724,13 @@ static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cl
ast_cli(a->fd,"%-22s: %d-%d\n", "Parked call extensions", ast_cli(a->fd,"%-22s: %d-%d\n", "Parked call extensions",
curlot->cfg.parking_start, curlot->cfg.parking_stop); curlot->cfg.parking_start, curlot->cfg.parking_stop);
ast_cli(a->fd,"%-22s: %d ms\n", "Parkingtime", curlot->cfg.parkingtime); ast_cli(a->fd,"%-22s: %d ms\n", "Parkingtime", curlot->cfg.parkingtime);
ast_cli(a->fd,"%-22s: %s\n", "Comeback to origin",
(curlot->cfg.comebacktoorigin ? "yes" : "no"));
ast_cli(a->fd,"%-22s: %s%s\n", "Comeback context",
curlot->cfg.comebackcontext, (curlot->cfg.comebacktoorigin ?
" (comebacktoorigin=yes, not used)" : ""));
ast_cli(a->fd,"%-22s: %d\n", "Comeback dial time",
curlot->cfg.comebackdialtime);
ast_cli(a->fd,"%-22s: %s\n", "MusicOnHold class", curlot->cfg.mohclass); ast_cli(a->fd,"%-22s: %s\n", "MusicOnHold class", curlot->cfg.mohclass);
ast_cli(a->fd,"%-22s: %s\n", "Enabled", AST_CLI_YESNO(!curlot->disabled)); ast_cli(a->fd,"%-22s: %s\n", "Enabled", AST_CLI_YESNO(!curlot->disabled));
ast_cli(a->fd,"\n"); ast_cli(a->fd,"\n");