Various parking improvements.
authorMark Michelson <mmichelson@digium.com>
Fri, 20 Jan 2012 20:47:42 +0000 (20:47 +0000)
committerMark Michelson <mmichelson@digium.com>
Fri, 20 Jan 2012 20:47:42 +0000 (20:47 +0000)
* 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

CHANGES
UPGRADE.txt
configs/features.conf.sample
main/features.c

diff --git a/CHANGES b/CHANGES
index 67cddb5..b7d01ae 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -74,6 +74,14 @@ Applications
    manually specify timezone and format) There are other beneftis eg. format can
    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
 -----------------------------
  * Added command "cdr show pgsql status" to check connection status
index a876d07..e5a81a9 100644 (file)
 
 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:
  - MAILBOX_EXISTS has been deprecated. Use VM_INFO with the 'exists' parameter
    instead.
index 904c5d9..7f00fab 100644 (file)
@@ -19,19 +19,23 @@ context => parkedcalls          ; Which context parked calls are in (default par
 
 ;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'.
-                                ; 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
-                                ;         that parked this call.  This is done by saving off the name of the channel
-                                ;         that parked the call.
+                                ;         that parked this call. This is done by saving off the name of the channel
+                                ;         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
                                 ;         sending the call back to the extension that initially parked the call, or to
                                 ;         an entirely different destination.
                                 ;
                                 ;         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
-                                ;         the saved channel name that parked the call.  For example, if a SIP peer named
+                                ;         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
                                 ;         '0004F2040001' parked this call, the extension will be 'SIP_0004F2040001'.
                                 ;         (Note that an underscore is used here because the '/' character has a special
                                 ;         meaning in extension names for CallerID matching.)  If this extension does not
@@ -46,6 +50,18 @@ context => parkedcalls          ; Which context parked calls are in (default par
                                 ;         During the timeout procedure, the following variables are set
                                 ;         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
+                                ;         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
                                 ; 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
 ;parkpos => 800-850
 ;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.
 ; They can not be used while the remote party is ringing or in progress. If you require this feature you can use
index 1e0eaf1..b4b779d 100644 (file)
@@ -388,6 +388,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define DEFAULT_ATXFER_DROP_CALL                                       0               /*!< Do not drop call. */
 #define DEFAULT_ATXFER_LOOP_DELAY                                      10000   /*!< ms */
 #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 MAX_DIAL_FEATURE_OPTIONS 30
@@ -494,7 +497,9 @@ struct parkinglot_cfg {
        /*! Extension to park calls in this parking lot. */
        char parkext[AST_MAX_EXTENSION];
        /*! 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 */
        int parking_start;
        /*! Last available extension for parking */
@@ -542,6 +547,8 @@ struct parkinglot_cfg {
         */
        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 */
        unsigned int parkfindnext:1;
        /*! TRUE if the parking lot is exclusively accessed by parkext */
@@ -550,6 +557,8 @@ struct parkinglot_cfg {
        unsigned int parkaddhints:1;
        /*! TRUE if configuration is invalid and the parking lot should not be used. */
        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. */
@@ -609,7 +618,6 @@ static int adsipark;
 
 static int transferdigittimeout;
 static int featuredigittimeout;
-static int comebacktoorigin = 1;
 
 static int atxfernoanswertimeout;
 static unsigned int atxferdropcall;
@@ -4600,6 +4608,7 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds,
                                        parking_con_dial);
                        } else {
                                char returnexten[AST_MAX_EXTENSION];
+                               char comebackdialtime[AST_MAX_EXTENSION];
                                struct ast_datastore *features_datastore;
                                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)) {
                                        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),
                                                        &(dialfeatures->features_caller), buf, sizeof(buf)));
                                } else { /* Existing default */
                                        ast_log(LOG_NOTICE, "Dial features not found on %s, using default!\n",
                                                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);
 
+                               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,
                                        "Dial", ast_strdup(returnexten), ast_free_ptr, registrar)) {
                                        ast_log(LOG_ERROR,
@@ -4636,7 +4653,7 @@ static int manage_parked_call(struct parkeduser *pu, const struct pollfd *pfds,
                                 * those arguments.
                                 */
                                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);
                        } else {
                                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);
                                pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parkingslot);
                                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 {
                        /*
@@ -5331,12 +5348,18 @@ static const struct parkinglot_cfg parkinglot_cfg_default_default = {
        .parking_start = 701,
        .parking_stop = 750,
        .parkingtime = DEFAULT_PARK_TIME,
+       .comebackdialtime = DEFAULT_COMEBACK_DIAL_TIME,
+       .comebackcontext = DEFAULT_COMEBACK_CONTEXT,
+       .comebacktoorigin = DEFAULT_COMEBACK_TO_ORIGIN,
 };
 
 /*! Default configuration for normal parking lots. */
 static const struct parkinglot_cfg parkinglot_cfg_default = {
        .parkext = DEFAULT_PARK_EXTENSION,
        .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);
                } else if (!strcasecmp(var->name, "parkedcallrecording")) {
                        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;
        }
@@ -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);
                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) {
                cfg->is_invalid = 1;
        }
@@ -5718,7 +5757,6 @@ static int process_config(struct ast_config *cfg)
        atxfercallbackretries = DEFAULT_ATXFER_CALLBACK_RETRIES;
 
        /* Set global call parking defaults. */
-       comebacktoorigin = 1;
        courtesytone[0] = '\0';
        parkedplay = 0;
        adsipark = 0;
@@ -5784,8 +5822,6 @@ static int process_config(struct ast_config *cfg)
                        ast_copy_string(pickupsound, var->value, sizeof(pickupsound));
                } else if (!strcasecmp(var->name, "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",
                        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:      %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", "Enabled", AST_CLI_YESNO(!curlot->disabled));
                ast_cli(a->fd,"\n");