mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
Allow for transferer to retry when dialing an invalid extension.
This allows for a configurable number of attempts for a transferer to dial an extension to transfer the call to. For Asterisk 13, the default values are such that upgrading between versions will not cause a behaivour change. For trunk, though, the defaults will be changed to be more user-friendly. Review: https://reviewboard.asterisk.org/r/4167 ........ Merged revisions 428145 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@428146 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
20
CHANGES
20
CHANGES
@@ -47,6 +47,12 @@ CHANNEL
|
|||||||
* Added CHANNEL(onhold) item that returns 1 (onhold) and 0 (not-onhold) for
|
* Added CHANNEL(onhold) item that returns 1 (onhold) and 0 (not-onhold) for
|
||||||
the hold status of a channel.
|
the hold status of a channel.
|
||||||
|
|
||||||
|
DTMF Features
|
||||||
|
------------------
|
||||||
|
* The transferdialattempts default value has been changed from 1 to 3. The
|
||||||
|
transferinvalidsound has been changed from "pbx-invalid" to "privacy-incorrect".
|
||||||
|
These were changed to make DTMF transfers be more user-friendly by default.
|
||||||
|
|
||||||
|
|
||||||
Resources
|
Resources
|
||||||
------------------
|
------------------
|
||||||
@@ -59,6 +65,20 @@ res_musiconhold
|
|||||||
over the channel-set musicclass. This allows separate hold-music from
|
over the channel-set musicclass. This allows separate hold-music from
|
||||||
application (e.g. Queue or Dial) specified music.
|
application (e.g. Queue or Dial) specified music.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
--- Functionality changes from Asterisk 13.0.0 to Asterisk 13.1.0 ------------
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Transfers
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The features.conf general section has three new configurable options:
|
||||||
|
* transferdialattempts
|
||||||
|
* transferretrysound
|
||||||
|
* transferinvalidsound
|
||||||
|
For more information on what these options do, see the Asterisk wiki:
|
||||||
|
https://wiki.asterisk.org/wiki/x/W4fAAQ
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes from Asterisk 12 to Asterisk 13 --------------------
|
--- Functionality changes from Asterisk 12 to Asterisk 13 --------------------
|
||||||
|
@@ -24,6 +24,10 @@
|
|||||||
;atxferloopdelay = 10 ; Number of seconds to sleep between retries (if atxferdropcall = no)
|
;atxferloopdelay = 10 ; Number of seconds to sleep between retries (if atxferdropcall = no)
|
||||||
;atxfercallbackretries = 2 ; Number of times to attempt to send the call back to the transferer.
|
;atxfercallbackretries = 2 ; Number of times to attempt to send the call back to the transferer.
|
||||||
; By default, this is 2.
|
; By default, this is 2.
|
||||||
|
;transferdialattempts = 3 ; Number of times that a transferer may attempt to dial an extension before
|
||||||
|
; being kicked back to the original call.
|
||||||
|
;transferretrysound = "beep" ; Sound to play when a transferer fails to dial a valid extension.
|
||||||
|
;transferinvalidsound = "beeperr" ; Sound to play when a transferer fails to dial a valid extension and is out of retries.
|
||||||
|
|
||||||
|
|
||||||
; 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.
|
||||||
|
@@ -68,6 +68,10 @@ struct ast_features_xfer_config {
|
|||||||
AST_STRING_FIELD(atxferthreeway);
|
AST_STRING_FIELD(atxferthreeway);
|
||||||
/*! DTMF sequence used to swap which party the transferer is talking to */
|
/*! DTMF sequence used to swap which party the transferer is talking to */
|
||||||
AST_STRING_FIELD(atxferswap);
|
AST_STRING_FIELD(atxferswap);
|
||||||
|
/*! Sound played when an invalid extension is dialed, and the transferer should retry. */
|
||||||
|
AST_STRING_FIELD(transferretrysound);
|
||||||
|
/*! Sound played when an invalid extension is dialed, and the transferer is being returned to the call. */
|
||||||
|
AST_STRING_FIELD(transferinvalidsound);
|
||||||
);
|
);
|
||||||
/*! Seconds allowed between digit presses when dialing transfer destination */
|
/*! Seconds allowed between digit presses when dialing transfer destination */
|
||||||
unsigned int transferdigittimeout;
|
unsigned int transferdigittimeout;
|
||||||
@@ -79,6 +83,8 @@ struct ast_features_xfer_config {
|
|||||||
unsigned int atxfercallbackretries;
|
unsigned int atxfercallbackretries;
|
||||||
/*! Determines if the call is dropped on attended transfer failure */
|
/*! Determines if the call is dropped on attended transfer failure */
|
||||||
unsigned int atxferdropcall;
|
unsigned int atxferdropcall;
|
||||||
|
/*! Number of dial attempts allowed for blind/attended transfers */
|
||||||
|
unsigned int transferdialattempts;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
#include "asterisk/stasis_bridges.h"
|
#include "asterisk/stasis_bridges.h"
|
||||||
#include "asterisk/features.h"
|
#include "asterisk/features.h"
|
||||||
#include "asterisk/format_cache.h"
|
#include "asterisk/format_cache.h"
|
||||||
|
#include "asterisk/test.h"
|
||||||
|
|
||||||
#define NORMAL_FLAGS (AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY \
|
#define NORMAL_FLAGS (AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY \
|
||||||
| AST_BRIDGE_FLAG_SMART)
|
| AST_BRIDGE_FLAG_SMART)
|
||||||
@@ -2977,7 +2978,11 @@ static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
int digit_timeout;
|
int digit_timeout;
|
||||||
|
int attempts = 0;
|
||||||
|
int max_attempts;
|
||||||
RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
|
RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
|
||||||
|
char *retry_sound;
|
||||||
|
char *invalid_sound;
|
||||||
|
|
||||||
ast_channel_lock(chan);
|
ast_channel_lock(chan);
|
||||||
xfer_cfg = ast_get_chan_features_xfer_config(chan);
|
xfer_cfg = ast_get_chan_features_xfer_config(chan);
|
||||||
@@ -2987,6 +2992,9 @@ static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
digit_timeout = xfer_cfg->transferdigittimeout * 1000;
|
digit_timeout = xfer_cfg->transferdigittimeout * 1000;
|
||||||
|
max_attempts = xfer_cfg->transferdialattempts;
|
||||||
|
retry_sound = ast_strdupa(xfer_cfg->transferretrysound);
|
||||||
|
invalid_sound = ast_strdupa(xfer_cfg->transferinvalidsound);
|
||||||
ast_channel_unlock(chan);
|
ast_channel_unlock(chan);
|
||||||
|
|
||||||
/* Play the simple "transfer" prompt out and wait */
|
/* Play the simple "transfer" prompt out and wait */
|
||||||
@@ -3002,24 +3010,48 @@ static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Drop to dialtone so they can enter the extension they want to transfer to */
|
/* Drop to dialtone so they can enter the extension they want to transfer to */
|
||||||
res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
|
do {
|
||||||
if (res < 0) {
|
++attempts;
|
||||||
/* Hangup or error */
|
memset(exten, 0, exten_len);
|
||||||
res = -1;
|
ast_test_suite_event_notify("TRANSFER_BEGIN_DIAL",
|
||||||
} else if (!res) {
|
"Channel: %s\r\n"
|
||||||
/* 0 for invalid extension dialed. */
|
"Attempt: %d",
|
||||||
if (ast_strlen_zero(exten)) {
|
ast_channel_name(chan), attempts);
|
||||||
ast_debug(1, "%s dialed no digits.\n", ast_channel_name(chan));
|
res = ast_app_dtget(chan, context, exten, exten_len, exten_len - 1, digit_timeout);
|
||||||
|
if (res < 0) {
|
||||||
|
/* Hangup or error */
|
||||||
|
res = -1;
|
||||||
|
} else if (!res) {
|
||||||
|
/* 0 for invalid extension dialed. */
|
||||||
|
if (ast_strlen_zero(exten)) {
|
||||||
|
ast_debug(1, "%s dialed no digits.\n", ast_channel_name(chan));
|
||||||
|
} else {
|
||||||
|
ast_debug(1, "%s dialed '%s@%s' does not exist.\n",
|
||||||
|
ast_channel_name(chan), exten, context);
|
||||||
|
}
|
||||||
|
if (attempts < max_attempts) {
|
||||||
|
ast_stream_and_wait(chan, retry_sound, AST_DIGIT_NONE);
|
||||||
|
} else {
|
||||||
|
ast_stream_and_wait(chan, invalid_sound, AST_DIGIT_NONE);
|
||||||
|
}
|
||||||
|
res = -1;
|
||||||
} else {
|
} else {
|
||||||
ast_debug(1, "%s dialed '%s@%s' does not exist.\n",
|
/* Dialed extension is valid. */
|
||||||
ast_channel_name(chan), exten, context);
|
res = 0;
|
||||||
}
|
}
|
||||||
ast_stream_and_wait(chan, "pbx-invalid", AST_DIGIT_NONE);
|
ast_test_suite_event_notify("TRANSFER_DIALLED",
|
||||||
res = -1;
|
"Channel: %s\r\n"
|
||||||
} else {
|
"Attempt: %d\r\n"
|
||||||
/* Dialed extension is valid. */
|
"Dialled: %s\r\n"
|
||||||
res = 0;
|
"Result: %s",
|
||||||
}
|
ast_channel_name(chan), attempts, exten, res == 0 ? "Success" : "Failure");
|
||||||
|
} while (res < 0 && attempts < max_attempts);
|
||||||
|
|
||||||
|
ast_test_suite_event_notify("TRANSFER_DIAL_FINAL",
|
||||||
|
"Channel: %s\r\n"
|
||||||
|
"Result: %s",
|
||||||
|
ast_channel_name(chan), res == 0 ? "Success" : "Failure");
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -132,6 +132,15 @@
|
|||||||
<configOption name="pickupfailsound">
|
<configOption name="pickupfailsound">
|
||||||
<synopsis>Sound to play to picker when a call cannot be picked up</synopsis>
|
<synopsis>Sound to play to picker when a call cannot be picked up</synopsis>
|
||||||
</configOption>
|
</configOption>
|
||||||
|
<configOption name="transferdialattempts" default="3">
|
||||||
|
<synopsis>Number of dial attempts allowed when attempting a transfer</synopsis>
|
||||||
|
</configOption>
|
||||||
|
<configOption name="transferretrysound" default="pbx-invalid">
|
||||||
|
<synopsis>Sound that is played when an incorrect extension is dialed and the transferer should try again.</synopsis>
|
||||||
|
</configOption>
|
||||||
|
<configOption name="transferinvalidsound" default="privacy-incorrect">
|
||||||
|
<synopsis>Sound that is played when an incorrect extension is dialed and the transferer has no attempts remaining.</synopsis>
|
||||||
|
</configOption>
|
||||||
</configObject>
|
</configObject>
|
||||||
<configObject name="featuremap">
|
<configObject name="featuremap">
|
||||||
<synopsis>DTMF options that can be triggered during bridged calls</synopsis>
|
<synopsis>DTMF options that can be triggered during bridged calls</synopsis>
|
||||||
@@ -306,6 +315,9 @@
|
|||||||
<enum name="pickupfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupfailsound']/synopsis/text())" /></para></enum>
|
<enum name="pickupfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupfailsound']/synopsis/text())" /></para></enum>
|
||||||
<enum name="courtesytone"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='courtesytone']/synopsis/text())" /></para></enum>
|
<enum name="courtesytone"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='courtesytone']/synopsis/text())" /></para></enum>
|
||||||
<enum name="recordingfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='recordingfailsound']/synopsis/text())" /></para></enum>
|
<enum name="recordingfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='recordingfailsound']/synopsis/text())" /></para></enum>
|
||||||
|
<enum name="transferdialattempts"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferdialattempts']/synopsis/text())" /></para></enum>
|
||||||
|
<enum name="transferretrysound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferretrysound']/synopsis/text())" /></para></enum>
|
||||||
|
<enum name="transferinvalidsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferinvalidsound']/synopsis/text())" /></para></enum>
|
||||||
</enumlist>
|
</enumlist>
|
||||||
</parameter>
|
</parameter>
|
||||||
</syntax>
|
</syntax>
|
||||||
@@ -366,6 +378,9 @@
|
|||||||
#define DEFAULT_ATXFER_COMPLETE "*2"
|
#define DEFAULT_ATXFER_COMPLETE "*2"
|
||||||
#define DEFAULT_ATXFER_THREEWAY "*3"
|
#define DEFAULT_ATXFER_THREEWAY "*3"
|
||||||
#define DEFAULT_ATXFER_SWAP "*4"
|
#define DEFAULT_ATXFER_SWAP "*4"
|
||||||
|
#define DEFAULT_TRANSFER_DIAL_ATTEMPTS 3
|
||||||
|
#define DEFAULT_TRANSFER_RETRY_SOUND "pbx-invalid"
|
||||||
|
#define DEFAULT_TRANSFER_INVALID_SOUND "privacy-incorrect"
|
||||||
|
|
||||||
/*! Default pickup options */
|
/*! Default pickup options */
|
||||||
#define DEFAULT_PICKUPEXTEN "*8"
|
#define DEFAULT_PICKUPEXTEN "*8"
|
||||||
@@ -773,6 +788,7 @@ static void xfer_copy(struct ast_features_xfer_config *dest, const struct ast_fe
|
|||||||
dest->atxferloopdelay = src->atxferloopdelay;
|
dest->atxferloopdelay = src->atxferloopdelay;
|
||||||
dest->atxfercallbackretries = src->atxfercallbackretries;
|
dest->atxfercallbackretries = src->atxfercallbackretries;
|
||||||
dest->atxferdropcall = src->atxferdropcall;
|
dest->atxferdropcall = src->atxferdropcall;
|
||||||
|
dest->transferdialattempts = src->transferdialattempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickup_copy(struct ast_features_pickup_config *dest, const struct ast_features_pickup_config *src)
|
static void pickup_copy(struct ast_features_pickup_config *dest, const struct ast_features_pickup_config *src)
|
||||||
@@ -882,6 +898,12 @@ static int xfer_set(struct ast_features_xfer_config *xfer, const char *name,
|
|||||||
ast_string_field_set(xfer, atxferthreeway, value);
|
ast_string_field_set(xfer, atxferthreeway, value);
|
||||||
} else if (!strcasecmp(name, "atxferswap")) {
|
} else if (!strcasecmp(name, "atxferswap")) {
|
||||||
ast_string_field_set(xfer, atxferswap, value);
|
ast_string_field_set(xfer, atxferswap, value);
|
||||||
|
} else if (!strcasecmp(name, "transferdialattempts")) {
|
||||||
|
res = ast_parse_arg(value, PARSE_INT32, &xfer->transferdialattempts);
|
||||||
|
} else if (!strcasecmp(name, "transferretrysound")) {
|
||||||
|
ast_string_field_set(xfer, transferretrysound, value);
|
||||||
|
} else if (!strcasecmp(name, "transferinvalidsound")) {
|
||||||
|
ast_string_field_set(xfer, transferinvalidsound, value);
|
||||||
} else {
|
} else {
|
||||||
/* Unrecognized option */
|
/* Unrecognized option */
|
||||||
res = -1;
|
res = -1;
|
||||||
@@ -917,6 +939,12 @@ static int xfer_get(struct ast_features_xfer_config *xfer, const char *field,
|
|||||||
ast_copy_string(buf, xfer->atxferthreeway, len);
|
ast_copy_string(buf, xfer->atxferthreeway, len);
|
||||||
} else if (!strcasecmp(field, "atxferswap")) {
|
} else if (!strcasecmp(field, "atxferswap")) {
|
||||||
ast_copy_string(buf, xfer->atxferswap, len);
|
ast_copy_string(buf, xfer->atxferswap, len);
|
||||||
|
} else if (!strcasecmp(field, "transferdialattempts")) {
|
||||||
|
snprintf(buf, len, "%u", xfer->transferdialattempts);
|
||||||
|
} else if (!strcasecmp(field, "transferretrysound")) {
|
||||||
|
ast_copy_string(buf, xfer->transferretrysound, len);
|
||||||
|
} else if (!strcasecmp(field, "transferinvalidsound")) {
|
||||||
|
ast_copy_string(buf, xfer->transferinvalidsound, len);
|
||||||
} else {
|
} else {
|
||||||
/* Unrecognized option */
|
/* Unrecognized option */
|
||||||
res = -1;
|
res = -1;
|
||||||
@@ -1731,6 +1759,12 @@ static int load_config(void)
|
|||||||
DEFAULT_ATXFER_THREEWAY, xfer_handler, 0);
|
DEFAULT_ATXFER_THREEWAY, xfer_handler, 0);
|
||||||
aco_option_register_custom(&cfg_info, "atxferswap", ACO_EXACT, global_options,
|
aco_option_register_custom(&cfg_info, "atxferswap", ACO_EXACT, global_options,
|
||||||
DEFAULT_ATXFER_SWAP, xfer_handler, 0);
|
DEFAULT_ATXFER_SWAP, xfer_handler, 0);
|
||||||
|
aco_option_register_custom(&cfg_info, "transferdialattempts", ACO_EXACT, global_options,
|
||||||
|
__stringify(DEFAULT_TRANSFER_DIAL_ATTEMPTS), xfer_handler, 0);
|
||||||
|
aco_option_register_custom(&cfg_info, "transferretrysound", ACO_EXACT, global_options,
|
||||||
|
DEFAULT_TRANSFER_RETRY_SOUND, xfer_handler, 0);
|
||||||
|
aco_option_register_custom(&cfg_info, "transferinvalidsound", ACO_EXACT, global_options,
|
||||||
|
DEFAULT_TRANSFER_INVALID_SOUND, xfer_handler, 0);
|
||||||
|
|
||||||
aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
|
aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
|
||||||
DEFAULT_PICKUPEXTEN, pickup_handler, 0);
|
DEFAULT_PICKUPEXTEN, pickup_handler, 0);
|
||||||
|
Reference in New Issue
Block a user