Index: CHANGES =================================================================== --- CHANGES (revision 270257) +++ CHANGES (working copy) @@ -1475,6 +1475,8 @@ of the URI parameter to the AGI function call in your dial plan. Also note that specifying a port number in the AGI URI will disable SRV lookups, even if you use the hagi: protocol. + * Added PARK command to park a call via AGI. Accepts the same options as the + dialplan command. Returns the parking lot slot number if successful. Logger changes -------------- Index: include/asterisk/features.h =================================================================== --- include/asterisk/features.h (revision 270257) +++ include/asterisk/features.h (working copy) @@ -105,9 +105,23 @@ */ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout); -/*! +/*! + * \brief Park a call via a masqueraded channel with parking arguments + * \param rchan the real channel to be parked + * \param host the channel to have the parking read to. + * \param timeout is a timeout in milliseconds + * \param extout is a parameter to an int that will hold the parked location, or NULL if you want. + * \param data is the list of options to be passed to the parking application + * + * Masquerade the channel rchan into a new, empty channel which is then parked with ast_park_call + * \retval 0 on success. + * \retval -1 on failure. +*/ +int ast_masq_park_call_args(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout, const char *data); + +/*! * \brief Determine system parking extension - * \returns the call parking extension for drivers that provide special call parking help + * \returns the call parking extension for drivers that provide special call parking help */ const char *ast_parking_ext(void); Index: main/features.c =================================================================== --- main/features.c (revision 270257) +++ main/features.c (working copy) @@ -1020,10 +1020,11 @@ if (!args) { args = &park_args; - args->timeout = timeout; - args->extout = extout; } + args->timeout = timeout; + args->extout = extout; + if ((args->pu = park_space_reserve(rchan, peer, args)) == NULL) { if (peer) ast_stream_and_wait(peer, "beeperr", ""); @@ -1071,15 +1072,79 @@ return 0; } +AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS + AST_APP_OPTION('r', AST_PARK_OPT_RINGING), + AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE), + AST_APP_OPTION('s', AST_PARK_OPT_SILENCE), +END_OPTIONS ); + +static int parse_parking_options(const char *data, struct ast_park_call_args *args) +{ + char *parse = NULL; + struct ast_flags flags = { 0 }; + + AST_DECLARE_APP_ARGS(app_args, + AST_APP_ARG(timeout); + AST_APP_ARG(return_con); + AST_APP_ARG(return_ext); + AST_APP_ARG(return_pri); + AST_APP_ARG(options); + ); + + parse = ast_strdupa(data); + ast_debug(1, "Parsing parking options %s\n", parse); + AST_STANDARD_APP_ARGS(app_args, parse); + + if (parse) { + if (!ast_strlen_zero(app_args.timeout)) { + if (sscanf(app_args.timeout, "%30d", &args->timeout) != 1) { + ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout); + args->timeout = 0; + } + ast_debug(1, "Parking lot timeout: %d\n", args->timeout); + } + if (!ast_strlen_zero(app_args.return_con)) { + args->return_con = app_args.return_con; + } + ast_debug(1, "Return Context: %s\n", args->return_con); + if (!ast_strlen_zero(app_args.return_ext)) { + args->return_ext = app_args.return_ext; + } + if (!ast_strlen_zero(app_args.return_pri)) { + if (sscanf(app_args.return_pri, "%30d", &args->return_pri) != 1) { + ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri); + args->return_pri = 0; + } + } + } + + ast_app_parse_options(park_call_options, &flags, NULL, app_args.options); + ast_debug(1, "Return Context Again: %s\n", args->return_con); + args->flags = flags.flags; + ast_debug(1, "Flags: %d\n", flags.flags); + + return 0; +} + /* Park call via masqueraded 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); } +/* Park call via masqueraded channel with arguments */ +int ast_masq_park_call_args(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout, const char *data) +{ + struct ast_park_call_args args = { + .orig_chan_name = ast_strdupa(rchan->name), + }; + parse_parking_options(data, &args); + return masq_park_call(rchan, peer, timeout, extout, 0, &args); +} + static int masq_park_call_announce_args(struct ast_channel *rchan, struct ast_channel *peer, struct ast_park_call_args *args) { - return masq_park_call(rchan, peer, 0, NULL, 1, args); + return masq_park_call(rchan, peer, args->timeout, args->extout, 1, args); } static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel *peer, int timeout, int *extout) @@ -3780,12 +3845,6 @@ return copylot; } -AST_APP_OPTIONS(park_call_options, BEGIN_OPTIONS - AST_APP_OPTION('r', AST_PARK_OPT_RINGING), - AST_APP_OPTION('R', AST_PARK_OPT_RANDOMIZE), - AST_APP_OPTION('s', AST_PARK_OPT_SILENCE), -END_OPTIONS ); - /*! \brief Park a call */ static int park_call_exec(struct ast_channel *chan, const char *data) { @@ -3800,18 +3859,6 @@ lot context eventually */ int res = 0; - char *parse = NULL; - AST_DECLARE_APP_ARGS(app_args, - AST_APP_ARG(timeout); - AST_APP_ARG(return_con); - AST_APP_ARG(return_ext); - AST_APP_ARG(return_pri); - AST_APP_ARG(options); - ); - - parse = ast_strdupa(data); - AST_STANDARD_APP_ARGS(app_args, parse); - ast_copy_string(orig_exten, chan->exten, sizeof(orig_exten)); /* Setup the exten/priority to be s/1 since we don't know @@ -3832,32 +3879,9 @@ struct ast_park_call_args args = { .orig_chan_name = orig_chan_name, }; - struct ast_flags flags = { 0 }; - if (parse) { - if (!ast_strlen_zero(app_args.timeout)) { - if (sscanf(app_args.timeout, "%30d", &args.timeout) != 1) { - ast_log(LOG_WARNING, "Invalid timeout '%s' provided\n", app_args.timeout); - args.timeout = 0; - } - } - if (!ast_strlen_zero(app_args.return_con)) { - args.return_con = app_args.return_con; - } - if (!ast_strlen_zero(app_args.return_ext)) { - args.return_ext = app_args.return_ext; - } - if (!ast_strlen_zero(app_args.return_pri)) { - if (sscanf(app_args.return_pri, "%30d", &args.return_pri) != 1) { - ast_log(LOG_WARNING, "Invalid priority '%s' specified\n", app_args.return_pri); - args.return_pri = 0; - } - } - } + parse_parking_options(data, &args); - ast_app_parse_options(park_call_options, &flags, NULL, app_args.options); - args.flags = flags.flags; - res = masq_park_call_announce_args(chan, chan, &args); /* Continue on in the dialplan */ if (res == 1) { Index: res/res_agi.c =================================================================== --- res/res_agi.c (revision 270257) +++ res/res_agi.c (working copy) @@ -316,6 +316,18 @@ Does nothing. + + + Park the current channel + + + + + + Parks the current call and returns the parking lot number into into which the call was parked. + Returns 1 and the parking lot number if successful, 0 otherwise. + + Receives one character from channels supporting it. @@ -2629,6 +2641,25 @@ return RESULT_SUCCESS; } +static int handle_park(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) +{ + int res; + int space; + + if (argc == 2) { + res = ast_masq_park_call_args(chan, NULL, 0, &space, argv[1]); + } else { + res = ast_masq_park_call(chan, NULL, 0, &space); + } + + if (!res) { + ast_agi_send(agi->fd, chan, "200 result=1 (%d)\n", space); + } else { + ast_agi_send(agi->fd, chan, "200 result=0\n"); + } + return RESULT_SUCCESS; +} + static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[]) { if (argc < 3) { @@ -2946,9 +2977,10 @@ { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 }, { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 }, { { "noop", NULL }, handle_noop, NULL, NULL, 1 }, + { { "park", NULL }, handle_park, NULL, NULL, 1 }, { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 }, { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 }, - { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 }, + { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 }, { { "say", "alpha", NULL }, handle_sayalpha, NULL, NULL, 0}, { { "say", "digits", NULL }, handle_saydigits, NULL, NULL, 0 }, { { "say", "number", NULL }, handle_saynumber, NULL, NULL, 0 },