dect
/
asterisk
Archived
13
0
Fork 0

Merge branch 'master' of 192.168.0.100:/repos/git/asterisk

This commit is contained in:
Patrick McHardy 2011-04-10 18:18:21 +02:00
commit 2ac6b3ac85
27 changed files with 1896 additions and 1280 deletions

14
CHANGES
View File

@ -28,12 +28,19 @@ Asterisk HTTP Server
--------------------------
* The HTTP Server can bind to IPv6 addresses.
chan_dahdi
--------------------------
* Busy tone patterns featuring 2 silence and 2 tone lengths can now be used
with busydetect. usage example: busypattern=200,200,200,600
CLI Changes
--------------------------
* New 'gtalk show settings' command showing the current settings loaded from
gtalk.conf.
* The 'logger reload' command now supports an optional argument, specifying an
alternate configuration file to use.
* 'dialplan add extension' command will now automatically create a context if
the specified context does not exist with a message indicated it did so.
CDR
--------------------------
@ -77,6 +84,13 @@ MixMonitor
(mixed) recording. The mixed file name argument is optional now as long
as at least one recording option is used.
FollowMe
--------------------------
* Added a new option, l, which will disable local call optimization for
channels involved with the FollowMe thread. Use this option to improve
compatability for a FollowMe call with certain dialplan apps, options, and
functions.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 1.6.2 to Asterisk 1.8 ----------------
------------------------------------------------------------------------------

View File

@ -428,7 +428,7 @@ static int my_load_module(int reload)
int res;
struct ast_config *cfg;
struct ast_variable *var;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
struct ast_flags config_flags = { 0 };
struct column *entry;
char *temp;
struct ast_str *compat;
@ -439,6 +439,9 @@ static int my_load_module(int reload)
my_bool my_bool_true = 1;
#endif
/* Cannot use a conditionally different flag, because the table layout may
* have changed, which is not detectable by config file change detection,
* but should still cause the configuration to be re-parsed. */
cfg = ast_config_load(config, config_flags);
if (!cfg) {
ast_log(LOG_WARNING, "Unable to load config for mysql CDR's: %s\n", config);

View File

@ -1193,6 +1193,7 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
char *callToken = (char *)NULL;
int res = -1;
if (!p) return -1;
@ -1258,10 +1259,14 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
}
break;
case AST_CONTROL_SRCUPDATE:
ast_rtp_instance_update_source(p->rtp);
if (p->rtp) {
ast_rtp_instance_update_source(p->rtp);
}
break;
case AST_CONTROL_SRCCHANGE:
ast_rtp_instance_change_source(p->rtp);
if (p->rtp) {
ast_rtp_instance_change_source(p->rtp);
}
break;
case AST_CONTROL_CONNECTED_LINE:
if (!ast->connected.id.name.valid
@ -1297,6 +1302,7 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
if (!p->chmodepend && !p->faxmode) {
ooRequestChangeMode(p->callToken, 1);
p->chmodepend = 1;
res = 0;
}
break;
@ -1305,6 +1311,7 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
if (!p->chmodepend && p->faxmode) {
ooRequestChangeMode(p->callToken, 0);
p->chmodepend = 1;
res = 0;
}
break;
@ -1330,7 +1337,7 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
ast_verbose("++++ ooh323_indicate %d on %s\n", condition, callToken);
free(callToken);
return -1;
return res;
}
static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)

View File

@ -86,6 +86,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<option name="d">
<para>Disable the 'Please hold while we try to connect your call' announcement.</para>
</option>
<option name="l">
<para>Disable local call optimization so that applications with
audio hooks between the local bridge don't get dropped when the
calls get joined directly.</para>
</option>
</optionlist>
</parameter>
</syntax>
@ -168,7 +173,8 @@ enum {
FOLLOWMEFLAG_RECORDNAME = (1 << 1),
FOLLOWMEFLAG_UNREACHABLEMSG = (1 << 2),
FOLLOWMEFLAG_DISABLEHOLDPROMPT = (1 << 3),
FOLLOWMEFLAG_NOANSWER = (1 << 4)
FOLLOWMEFLAG_NOANSWER = (1 << 4),
FOLLOWMEFLAG_DISABLEOPTIMIZATION = (1 << 5),
};
AST_APP_OPTIONS(followme_opts, {
@ -177,6 +183,7 @@ AST_APP_OPTIONS(followme_opts, {
AST_APP_OPTION('n', FOLLOWMEFLAG_UNREACHABLEMSG ),
AST_APP_OPTION('d', FOLLOWMEFLAG_DISABLEHOLDPROMPT ),
AST_APP_OPTION('N', FOLLOWMEFLAG_NOANSWER ),
AST_APP_OPTION('l', FOLLOWMEFLAG_DISABLEOPTIMIZATION ),
});
static int ynlongest = 0;
@ -838,9 +845,9 @@ static void findmeexec(struct fm_args *tpargs)
}
if (!strcmp(tpargs->context, ""))
snprintf(dialarg, sizeof(dialarg), "%s", number);
snprintf(dialarg, sizeof(dialarg), "%s%s", number, ast_test_flag(&tpargs->followmeflags, FOLLOWMEFLAG_DISABLEOPTIMIZATION) ? "/n" : "");
else
snprintf(dialarg, sizeof(dialarg), "%s@%s", number, tpargs->context);
snprintf(dialarg, sizeof(dialarg), "%s@%s%s", number, tpargs->context, ast_test_flag(&tpargs->followmeflags, FOLLOWMEFLAG_DISABLEOPTIMIZATION) ? "/n" : "");
tmpuser = ast_calloc(1, sizeof(*tmpuser));
if (!tmpuser) {

View File

@ -2331,6 +2331,14 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
}
}
ast_verb(3, "Setting conference duration limit to: %ldms.\n", timelimit);
if (play_warning) {
ast_verb(3, "Setting warning time to %ldms from the conference duration limit.\n", play_warning);
}
if (warning_freq) {
ast_verb(3, "Setting warning frequency to %ldms.\n", warning_freq);
}
ast_channel_lock(chan);
if ((var = pbx_builtin_getvar_helper(chan, "CONF_LIMIT_WARNING_FILE"))) {
var = ast_strdupa(var);
@ -4400,11 +4408,12 @@ static int conf_exec(struct ast_channel *chan, const char *data)
if (((!ast_strlen_zero(cnf->pin) &&
!ast_test_flag64(&confflags, CONFFLAG_ADMIN)) ||
(!ast_strlen_zero(cnf->pinadmin) &&
ast_test_flag64(&confflags, CONFFLAG_ADMIN)) ||
(!ast_strlen_zero(cnf->pin) &&
ast_strlen_zero(cnf->pinadmin) &&
ast_test_flag64(&confflags, CONFFLAG_ADMIN))) &&
(!(cnf->users == 0 && cnf->isdynamic))) {
ast_test_flag64(&confflags, CONFFLAG_ADMIN)) ||
(!ast_strlen_zero(cnf->pin) &&
ast_strlen_zero(cnf->pinadmin) &&
ast_test_flag64(&confflags, CONFFLAG_ADMIN))) &&
((!(cnf->users == 0 && cnf->isdynamic)) ||
ast_test_flag64(&confflags, CONFFLAG_ALWAYSPROMPT))) {
char pin[MAX_PIN] = "";
int j;
@ -4856,12 +4865,12 @@ static int action_meetmelist(struct mansession *s, const struct message *m)
/* Find the right conference */
AST_LIST_LOCK(&confs);
AST_LIST_TRAVERSE(&confs, cnf, list) {
user_iter = ao2_iterator_init(cnf->usercontainer, 0);
/* If we ask for one particular, and this isn't it, skip it */
if (!ast_strlen_zero(conference) && strcmp(cnf->confno, conference))
continue;
/* Show all the users */
user_iter = ao2_iterator_init(cnf->usercontainer, 0);
while ((user = ao2_iterator_next(&user_iter))) {
total++;
astman_append(s,

View File

@ -201,6 +201,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</variable>
</variablelist>
</description>
<see-also>
<ref type="application">VoiceMailMain</ref>
</see-also>
</application>
<application name="VoiceMailMain" language="en_US">
<synopsis>
@ -259,6 +262,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</enum>
</enumlist>
</description>
<see-also>
<ref type="application">VoiceMail</ref>
</see-also>
</application>
<application name="MailboxExists" language="en_US">
<synopsis>
@ -3397,7 +3403,7 @@ static int retrieve_file(char *dir, int msgnum)
ast_odbc_release_obj(obj);
} else
ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
yuck:
if (f)
fclose(f);
if (fd > -1)
@ -3413,7 +3419,8 @@ yuck:
* This method is used when mailboxes are stored in an ODBC back end.
* Typical use to set the msgnum would be to take the value returned from this method and add one to it.
*
* \return the value of zero or greaterto indicate the last message index in use, -1 to indicate none.
* \return the value of zero or greater to indicate the last message index in use, -1 to indicate none.
*/
static int last_message_index(struct ast_vm_user *vmu, char *dir)
{
@ -3428,7 +3435,8 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir)
struct odbc_obj *obj;
obj = ast_odbc_request_obj(odbc_database, 0);
if (obj) {
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
snprintf(sql, sizeof(sql), "SELECT msgnum FROM %s WHERE dir=? order by msgnum desc limit 1", odbc_table);
stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
if (!stmt) {
ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
@ -3437,7 +3445,12 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir)
}
res = SQLFetch(stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
if (res == SQL_NO_DATA) {
ast_log(AST_LOG_DEBUG, "Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
} else {
ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
}
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
goto yuck;
@ -3450,12 +3463,13 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir)
goto yuck;
}
if (sscanf(rowdata, "%30d", &x) != 1)
ast_log(AST_LOG_WARNING, "Failed to read message count!\n");
ast_log(AST_LOG_WARNING, "Failed to read message index!\n");
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
return x;
} else
ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
yuck:
return x - 1;
}
@ -3510,25 +3524,63 @@ static int message_exists(char *dir, int msgnum)
ast_odbc_release_obj(obj);
} else
ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
yuck:
return x;
}
/*!
* \brief returns the one-based count for messages.
* \brief returns the number of messages found.
* \param vmu
* \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause.
*
* This method is used when mailboxes are stored in an ODBC back end.
* The message index is zero-based, the first message will be index 0. For convenient display it is good to have the
* one-based messages.
* This method just calls last_message_index and returns +1 of its value.
*
* \return the value greater than zero on success to indicate the one-based count of messages, less than zero on error.
* \return The count of messages being zero or more, less than zero on error.
*/
static int count_messages(struct ast_vm_user *vmu, char *dir)
{
return last_message_index(vmu, dir) + 1;
int x = 0;
int res;
SQLHSTMT stmt;
char sql[PATH_MAX];
char rowdata[20];
char *argv[] = { dir };
struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
struct odbc_obj *obj;
obj = ast_odbc_request_obj(odbc_database, 0);
if (obj) {
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
if (!stmt) {
ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
ast_odbc_release_obj(obj);
goto yuck;
}
res = SQLFetch(stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
goto yuck;
}
res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
goto yuck;
}
if (sscanf(rowdata, "%30d", &x) != 1)
ast_log(AST_LOG_WARNING, "Failed to read message count!\n");
SQLFreeHandle (SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
return x;
} else
ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return x - 1;
}
/*!
@ -5093,7 +5145,6 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *
if (obj) {
ast_odbc_release_obj(obj);
}
return x;
}
@ -6020,7 +6071,7 @@ leave_vm_out:
return res;
}
#if !defined(IMAP_STORAGE) && !defined(ODBC_STORAGE)
#if !defined(IMAP_STORAGE)
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
{
/* we know the actual number of messages, so stop process when number is hit */
@ -7765,11 +7816,9 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
if (last_msg < -1) {
return last_msg;
#ifndef ODBC_STORAGE
} else if (vms->lastmsg != last_msg) {
ast_log(LOG_NOTICE, "Resequencing mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
resequence_mailbox(vmu, vms->curdir, count_msg);
#endif
ast_log(LOG_NOTICE, "Resequencing Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg);
resequence_mailbox(vmu, vms->curdir, count_msg);
}
return 0;
@ -7779,7 +7828,9 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
{
int x = 0;
#ifndef IMAP_STORAGE
int last_msg_idx;
int res = 0, nummsg;
char fn2[PATH_MAX];
#endif
@ -7795,8 +7846,14 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
return ERROR_LOCK_PATH;
}
/* update count as message may have arrived while we've got mailbox open */
last_msg_idx = last_message_index(vmu, vms->curdir);
if (last_msg_idx != vms->lastmsg) {
ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg);
}
/* must check up to last detected message, just in case it is erroneously greater than maxmsg */
for (x = 0; x < vms->lastmsg + 1; x++) {
for (x = 0; x < last_msg_idx + 1; x++) {
if (!vms->deleted[x] && ((strcasecmp(vms->curbox, "INBOX") && strcasecmp(vms->curbox, "Urgent")) || !vms->heard[x] || (vms->heard[x] && !ast_test_flag(vmu, VM_MOVEHEARD)))) {
/* Save this message. It's not in INBOX or hasn't been heard */
make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
@ -10202,7 +10259,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
#endif
break;
case '8': /* Forward the current messgae */
case '8': /* Forward the current message */
if (vms.lastmsg > -1) {
cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
if (cmd == ERROR_LOCK_PATH) {

View File

@ -571,9 +571,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
}
break;
case SQL_INTEGER:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
int integer = 0;
if (strcasecmp(entry->name, "eventtype") == 0) {
integer = (int) record.event_type;
@ -590,9 +588,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
}
break;
case SQL_BIGINT:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
long long integer = 0;
if (strcasecmp(entry->name, "eventtype") == 0) {
integer = (long long) record.event_type;
@ -609,9 +605,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
}
break;
case SQL_SMALLINT:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
short integer = 0;
if (strcasecmp(entry->name, "eventtype") == 0) {
integer = (short) record.event_type;
@ -628,9 +622,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
}
break;
case SQL_TINYINT:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
char integer = 0;
if (strcasecmp(entry->name, "eventtype") == 0) {
integer = (char) record.event_type;
@ -647,9 +639,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
}
break;
case SQL_BIT:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
char integer = 0;
if (strcasecmp(entry->name, "eventtype") == 0) {
integer = (char) record.event_type;
@ -669,9 +659,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
break;
case SQL_NUMERIC:
case SQL_DECIMAL:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
double number = 0.0;
if (strcasecmp(entry->name, "eventtype") == 0) {
number = (double)record.event_type;
@ -690,9 +678,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
case SQL_FLOAT:
case SQL_REAL:
case SQL_DOUBLE:
if (ast_strlen_zero(colptr)) {
continue;
} else {
{
double number = 0.0;
if (strcasecmp(entry->name, "eventtype") == 0) {
number = (double) record.event_type;

View File

@ -1115,15 +1115,10 @@ struct dahdi_pvt {
*/
int busycount;
/*!
* \brief Length of "busy" tone on time.
* \note Set from the "busypattern" value read in from chan_dahdi.conf
* \brief Busy cadence pattern description.
* \note Set from the "busypattern" value read from chan_dahdi.conf
*/
int busy_tonelength;
/*!
* \brief Length of "busy" tone off time.
* \note Set from the "busypattern" value read in from chan_dahdi.conf
*/
int busy_quietlength;
struct ast_dsp_busy_pattern busy_cadence;
/*!
* \brief Bitmapped call progress detection flags. CALLPROGRESS_xxx values.
* \note Bits set from the "callprogress" and "faxdetect" values read in from chan_dahdi.conf
@ -3243,12 +3238,7 @@ static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
/* This is a B channel interface. */
++num_b_chans;
if (pri->pvts[idx]->owner
#if defined(HAVE_PRI_SERVICE_MESSAGES)
/* Out-of-service B channels are "in-use". */
|| pri->pvts[idx]->service_status
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
) {
if (!sig_pri_is_chan_available(pri->pvts[idx])) {
++in_use;
}
if (!pri->pvts[idx]->inalarm) {
@ -3330,6 +3320,7 @@ static struct sig_pri_callback dahdi_pri_callbacks =
.dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
.lock_private = my_lock_private,
.unlock_private = my_unlock_private,
.deadlock_avoidance_private = my_deadlock_avoidance_private,
.new_ast_channel = my_new_pri_ast_channel,
.fixup_chans = my_pri_fixup_chans,
.set_alarm = my_set_alarm,
@ -3493,6 +3484,7 @@ static struct sig_ss7_callback dahdi_ss7_callbacks =
{
.lock_private = my_lock_private,
.unlock_private = my_unlock_private,
.deadlock_avoidance_private = my_deadlock_avoidance_private,
.set_echocanceller = my_set_echocanceller,
.set_loopback = my_ss7_set_loopback,
@ -6463,11 +6455,9 @@ hangup_out:
p->cidspill = NULL;
ast_mutex_unlock(&p->lock);
ast_module_unref(ast_module_info->self);
ast_verb(3, "Hungup '%s'\n", ast->name);
ast_mutex_lock(&iflock);
if (p->restartpending) {
num_restart_pending--;
}
@ -6476,6 +6466,8 @@ hangup_out:
destroy_channel(p, 0);
}
ast_mutex_unlock(&iflock);
ast_module_unref(ast_module_info->self);
return 0;
}
@ -8776,14 +8768,27 @@ static struct ast_frame *dahdi_exception(struct ast_channel *ast)
static struct ast_frame *dahdi_read(struct ast_channel *ast)
{
struct dahdi_pvt *p = ast->tech_pvt;
struct dahdi_pvt *p;
int res;
int idx;
void *readbuf;
struct ast_frame *f;
/*
* For analog channels, we must do deadlock avoidance because
* analog ports can have more than one Asterisk channel using
* the same private structure.
*/
p = ast->tech_pvt;
while (ast_mutex_trylock(&p->lock)) {
CHANNEL_DEADLOCK_AVOIDANCE(ast);
/*
* For PRI channels, we must refresh the private pointer because
* the call could move to another B channel while the Asterisk
* channel is unlocked.
*/
p = ast->tech_pvt;
}
idx = dahdi_get_index(ast, p, 0);
@ -9542,7 +9547,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
ast_dsp_set_call_progress_zone(i->dsp, progzone);
if (i->busydetect && CANBUSYDETECT(i)) {
ast_dsp_set_busy_count(i->dsp, i->busycount);
ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
}
}
}
@ -11322,7 +11327,9 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
switch (i->sig) {
#if defined(HAVE_PRI)
case SIG_PRI_LIB_HANDLE_CASES:
ast_mutex_lock(&i->lock);
sig_pri_chan_alarm_notify(i->sig_pvt, 1);
ast_mutex_unlock(&i->lock);
break;
#endif /* defined(HAVE_PRI) */
#if defined(HAVE_SS7)
@ -11340,7 +11347,9 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
switch (i->sig) {
#if defined(HAVE_PRI)
case SIG_PRI_LIB_HANDLE_CASES:
ast_mutex_lock(&i->lock);
sig_pri_chan_alarm_notify(i->sig_pvt, 0);
ast_mutex_unlock(&i->lock);
break;
#endif /* defined(HAVE_PRI) */
#if defined(HAVE_SS7)
@ -12615,8 +12624,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
}
tmp->busydetect = conf->chan.busydetect;
tmp->busycount = conf->chan.busycount;
tmp->busy_tonelength = conf->chan.busy_tonelength;
tmp->busy_quietlength = conf->chan.busy_quietlength;
tmp->busy_cadence = conf->chan.busy_cadence;
tmp->callprogress = conf->chan.callprogress;
tmp->waitfordialtone = conf->chan.waitfordialtone;
tmp->cancallforward = conf->chan.cancallforward;
@ -12751,7 +12759,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
switch (tmp->sig) {
#ifdef HAVE_PRI
case SIG_PRI_LIB_HANDLE_CASES:
sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
sig_pri_set_alarm(tmp->sig_pvt, !si.alarms);
break;
#endif
#if defined(HAVE_SS7)
@ -13495,6 +13503,14 @@ static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap
tmp = analog_request(p->sig_pvt, &callwait, requestor);
#ifdef HAVE_PRI
} else if (dahdi_sig_pri_lib_handles(p->sig)) {
/*
* We already have the B channel reserved for this call. We
* just need to make sure that dahdi_hangup() has completed
* cleaning up before continuing.
*/
ast_mutex_lock(&p->lock);
ast_mutex_unlock(&p->lock);
sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
sizeof(p->dnid));
tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
@ -13509,18 +13525,23 @@ static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap
if (!tmp) {
p->outgoing = 0;
#if defined(HAVE_PRI)
#if defined(HAVE_PRI_CALL_WAITING)
switch (p->sig) {
case SIG_PRI_LIB_HANDLE_CASES:
#if defined(HAVE_PRI_CALL_WAITING)
if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
/*
* This should be the last thing to clear when we are done with
* the channel.
*/
((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
break;
default:
break;
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
#endif /* defined(HAVE_PRI) */
} else {
snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
@ -15120,7 +15141,7 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
#endif
ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
ast_cli(a->fd, " Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
}
ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
@ -15200,6 +15221,9 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
ast_cli(a->fd, "Resetting ");
if (chan->call)
ast_cli(a->fd, "Call ");
if (chan->allocated) {
ast_cli(a->fd, "Allocated ");
}
ast_cli(a->fd, "\n");
if (tmp->logicalspan)
ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
@ -16664,6 +16688,41 @@ static unsigned long dahdi_display_text_option(const char *value)
/*! process_dahdi() - No warnings on non-existing cofiguration keywords */
#define PROC_DAHDI_OPT_NOWARN (1 << 1)
static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
{
int count_pattern = 0;
int norval = 0;
char *temp = NULL;
for (; ;) {
/* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
break;
}
busy_cadence->pattern[count_pattern] = norval;
count_pattern++;
if (count_pattern == 4) {
break;
}
temp = strchr(v->value, ',');
if (temp == NULL) {
break;
}
v->value = temp + 1;
}
busy_cadence->length = count_pattern;
if (count_pattern % 2 != 0) {
/* The pattern length must be divisible by two */
ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
}
}
static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
{
struct dahdi_pvt *tmp;
@ -16789,9 +16848,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
} else if (!strcasecmp(v->name, "busycount")) {
confp->chan.busycount = atoi(v->value);
} else if (!strcasecmp(v->name, "busypattern")) {
if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
}
parse_busy_pattern(v, &confp->chan.busy_cadence);
} else if (!strcasecmp(v->name, "callprogress")) {
confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
if (ast_true(v->value))
@ -17824,7 +17881,8 @@ static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct
* \brief Setup DAHDI channel driver.
*
* \param reload enum: load_module(0), reload(1), restart(2).
* \param base_conf Default config parameters. So cc_params can be properly destroyed.
* \param default_conf Default config parameters. So cc_params can be properly destroyed.
* \param base_conf Default config parameters per section. So cc_params can be properly destroyed.
* \param conf Local config parameters. So cc_params can be properly destroyed.
*
* \retval 0 on success.
@ -17988,7 +18046,7 @@ static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, str
if (ucfg) {
const char *chans;
/* Reset base_conf, so things dont leak from dahdi_chan.conf */
/* Reset base_conf, so things don't leak from dahdi_chan.conf */
deep_copy_dahdi_chan_conf(base_conf, default_conf);
process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);

View File

@ -681,7 +681,7 @@ static ast_mutex_t cl_te_lock;
static enum event_response_e
cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
static void cl_queue_chan(struct chan_list *chan);
@ -8364,8 +8364,7 @@ static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
cb_log(2, port, " --> hangup\n");
ch->need_hangup = 0;
ch->need_queue_hangup = 0;
if (ch->ast) {
send_cause2ast(ch->ast, bc, ch);
if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
ast_hangup(ch->ast);
}
return;
@ -8373,13 +8372,15 @@ static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
if (!ch->need_queue_hangup) {
cb_log(2, port, " --> No need to queue hangup\n");
return;
}
ch->need_queue_hangup = 0;
if (ch->ast) {
send_cause2ast(ch->ast, bc, ch);
ast_queue_hangup_with_cause(ch->ast, bc->cause);
cb_log(2, port, " --> queue_hangup\n");
if (send_cause2ast(ch->ast, bc, ch)) {
ast_queue_hangup_with_cause(ch->ast, bc->cause);
cb_log(2, port, " --> queue_hangup\n");
}
} else {
cb_log(1, port, "Cannot hangup chan, no ast\n");
}
@ -8653,26 +8654,31 @@ static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch,
}
}
/*!
* \retval -1 if can hangup after calling.
* \retval 0 if cannot hangup after calling.
*/
static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
{
int can_hangup;
static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
if (!ast) {
chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
return;
return 0;
}
if (!bc) {
chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
return;
return 0;
}
if (!ch) {
chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
return;
return 0;
}
ast->hangupcause = bc->cause;
can_hangup = -1;
switch (bc->cause) {
case AST_CAUSE_UNALLOCATED:
case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
case AST_CAUSE_NO_ROUTE_DESTINATION:
@ -8699,15 +8705,16 @@ static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, s
chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
break;
}
chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
ast_queue_control(ast, AST_CONTROL_BUSY);
ch->need_busy = 0;
chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
ast_queue_control(ast, AST_CONTROL_BUSY);
/* The BUSY is likely to cause a hangup or the user needs to hear it. */
can_hangup = 0;
break;
}
return can_hangup;
}
@ -12453,29 +12460,28 @@ int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
/* allocates the jb-structure and initialize the elements*/
struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
{
int i;
struct misdn_jb *jb;
jb = ast_malloc(sizeof(*jb));
jb = ast_calloc(1, sizeof(*jb));
if (!jb) {
chan_misdn_log(-1, 0, "No free Mem for jb\n");
return NULL;
}
jb->size = size;
jb->upper_threshold = upper_threshold;
jb->wp = 0;
jb->rp = 0;
jb->state_full = 0;
jb->state_empty = 0;
jb->bytes_wrote = 0;
jb->samples = ast_malloc(size * sizeof(char));
//jb->wp = 0;
//jb->rp = 0;
//jb->state_full = 0;
//jb->state_empty = 0;
//jb->bytes_wrote = 0;
jb->samples = ast_calloc(size, sizeof(*jb->samples));
if (!jb->samples) {
ast_free(jb);
chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
return NULL;
}
jb->ok = ast_malloc(size * sizeof(char));
jb->ok = ast_calloc(size, sizeof(*jb->ok));
if (!jb->ok) {
ast_free(jb->samples);
ast_free(jb);
@ -12483,10 +12489,6 @@ struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
return NULL;
}
for (i = 0; i < size; i++) {
jb->ok[i] = 0;
}
ast_mutex_init(&jb->mutexjb);
return jb;

View File

@ -14656,16 +14656,20 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c
return 0;
}
/*! \brief Find out who the call is for.
We use the request uri as a destination.
This code assumes authentication has been done, so that the
device (peer/user) context is already set.
\return 0 on success (found a matching extension), non-zero on failure
\note If the incoming uri is a SIPS: uri, we are required to carry this across
the dialplan, so that the outbound call also is a sips: call or encrypted
IAX2 call. If that's not available, the call should FAIL.
*/
/*!
* \brief Find out who the call is for.
*
* \details
* We use the request uri as a destination.
* This code assumes authentication has been done, so that the
* device (peer/user) context is already set.
*
* \return 0 on success (found a matching extension), non-zero on failure
*
* \note If the incoming uri is a SIPS: uri, we are required to carry this across
* the dialplan, so that the outbound call also is a sips: call or encrypted
* IAX2 call. If that's not available, the call should FAIL.
*/
static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
{
char tmp[256] = "", *uri, *domain, *dummy = NULL;
@ -14691,6 +14695,14 @@ static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_re
SIP_PEDANTIC_DECODE(domain);
SIP_PEDANTIC_DECODE(uri);
if (ast_strlen_zero(uri)) {
/*
* Either there really was no extension found or the request
* URI had encoded nulls that made the string "empty". Use "s"
* as the extension.
*/
uri = "s";
}
ast_string_field_set(p, domain, domain);
@ -21003,6 +21015,8 @@ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, str
*/
static int handle_request_options(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
{
const char *msg;
enum sip_get_dest_result gotdest;
int res;
if (p->lastinvite) {
@ -21034,24 +21048,37 @@ static int handle_request_options(struct sip_pvt *p, struct sip_request *req, st
}
/* must go through authentication before getting here */
res = (get_destination(p, req, NULL) == SIP_GET_DEST_EXTEN_FOUND ? 0 : -1);
gotdest = get_destination(p, req, NULL);
build_contact(p);
if (ast_strlen_zero(p->context))
ast_string_field_set(p, context, sip_cfg.default_context);
if (ast_shutting_down())
transmit_response_with_allow(p, "503 Unavailable", req, 0);
else if (res < 0)
transmit_response_with_allow(p, "404 Not Found", req, 0);
else
transmit_response_with_allow(p, "200 OK", req, 0);
if (ast_shutting_down()) {
msg = "503 Unavailable";
} else {
msg = "404 Not Found";
switch (gotdest) {
case SIP_GET_DEST_INVALID_URI:
msg = "416 Unsupported URI scheme";
break;
case SIP_GET_DEST_PICKUP_EXTEN_FOUND:
case SIP_GET_DEST_REFUSED:
case SIP_GET_DEST_EXTEN_NOT_FOUND:
//msg = "404 Not Found";
break;
case SIP_GET_DEST_EXTEN_FOUND:
msg = "200 OK";
break;
}
}
transmit_response_with_allow(p, msg, req, 0);
/* Destroy if this OPTIONS was the opening request, but not if
it's in the middle of a normal call flow. */
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
return res;
return 0;
}
/*! \brief Handle the transfer part of INVITE with a replaces: header,

View File

@ -518,23 +518,31 @@ static void analog_all_subchannels_hungup(struct analog_pvt *p)
}
}
#if 0
static void analog_unlock_private(struct analog_pvt *p)
{
if (p->calls->unlock_private) {
p->calls->unlock_private(p->chan_pvt);
}
}
#endif
#if 0
static void analog_lock_private(struct analog_pvt *p)
{
if (p->calls->lock_private) {
p->calls->lock_private(p->chan_pvt);
}
}
#endif
static void analog_deadlock_avoidance_private(struct analog_pvt *p)
{
if (p->calls->deadlock_avoidance_private) {
p->calls->deadlock_avoidance_private(p->chan_pvt);
} else {
/* Fallback to manual avoidance if callback not present. */
analog_unlock_private(p);
usleep(1);
analog_lock_private(p);
}
}
/*!
* \internal
@ -563,12 +571,7 @@ static void analog_lock_sub_owner(struct analog_pvt *pvt, enum analog_sub sub_id
break;
}
/* We must unlock the private to avoid the possibility of a deadlock */
if (pvt->calls->deadlock_avoidance_private) {
pvt->calls->deadlock_avoidance_private(pvt->chan_pvt);
} else {
/* Don't use 100% CPU if required callback not present. */
usleep(1);
}
analog_deadlock_avoidance_private(pvt);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -167,6 +167,8 @@ struct sig_pri_callback {
void (* const unlock_private)(void *pvt);
/* Lock the private in the signalling private structure. ... */
void (* const lock_private)(void *pvt);
/* Do deadlock avoidance for the private signaling structure lock. */
void (* const deadlock_avoidance_private)(void *pvt);
/* Function which is called back to handle any other DTMF events that are received. Called by analog_handle_event. Why is this
* important to use, instead of just directly using events received before they are passed into the library? Because sometimes,
* (CWCID) the library absorbs DTMF events received. */
@ -305,6 +307,17 @@ struct sig_pri_chan {
unsigned int progress:1; /*!< TRUE if the call has seen inband-information progress through the network */
unsigned int resetting:1; /*!< TRUE if this channel is being reset/restarted */
/*!
* \brief TRUE when this channel is allocated.
*
* \details
* Needed to hold an outgoing channel allocation before the
* owner pointer is created.
*
* \note This is one of several items to check to see if a
* channel is available for use.
*/
unsigned int allocated:1;
unsigned int outgoing:1;
unsigned int digital:1;
/*! \brief TRUE if this interface has no B channel. (call hold and call waiting) */
@ -558,6 +571,7 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi
int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast);
int sig_pri_is_chan_available(struct sig_pri_chan *pvt);
int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel);
void sig_pri_init_pri(struct sig_pri_span *pri);
@ -569,6 +583,7 @@ int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char
void sig_pri_stop_pri(struct sig_pri_span *pri);
int sig_pri_start_pri(struct sig_pri_span *pri);
void sig_pri_set_alarm(struct sig_pri_chan *p, int in_alarm);
void sig_pri_chan_alarm_notify(struct sig_pri_chan *p, int noalarm);
void pri_event_alarm(struct sig_pri_span *pri, int index, int before_start_pri);

View File

@ -64,6 +64,16 @@ static void sig_ss7_lock_private(struct sig_ss7_chan *p)
}
}
static void sig_ss7_deadlock_avoidance_private(struct sig_ss7_chan *p)
{
if (p->calls->deadlock_avoidance_private) {
p->calls->deadlock_avoidance_private(p->chan_pvt);
} else {
/* Fallback to the old way if callback not present. */
SIG_SS7_DEADLOCK_AVOIDANCE(p);
}
}
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
{
p->inalarm = in_alarm;
@ -255,7 +265,7 @@ static void sig_ss7_lock_owner(struct sig_ss7_linkset *ss7, int chanpos)
}
/* We must unlock the SS7 to avoid the possibility of a deadlock */
ast_mutex_unlock(&ss7->lock);
SIG_SS7_DEADLOCK_AVOIDANCE(ss7->pvts[chanpos]);
sig_ss7_deadlock_avoidance_private(ss7->pvts[chanpos]);
ast_mutex_lock(&ss7->lock);
}
}
@ -1109,7 +1119,7 @@ static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7
do {
res = ast_mutex_trylock(&ss7->lock);
if (res) {
SIG_SS7_DEADLOCK_AVOIDANCE(pvt);
sig_ss7_deadlock_avoidance_private(pvt);
}
} while (res);
/* Then break the poll */

View File

@ -105,6 +105,8 @@ struct sig_ss7_callback {
void (* const unlock_private)(void *pvt);
/* Lock the private in the signaling private structure. */
void (* const lock_private)(void *pvt);
/* Do deadlock avoidance for the private signaling structure lock. */
void (* const deadlock_avoidance_private)(void *pvt);
int (* const set_echocanceller)(void *pvt, int enable);
void (* const set_loopback)(void *pvt, int enable);

View File

@ -1128,7 +1128,7 @@ int parse_name_andor_addr(char *uri, const char *scheme, char **name,
struct uriparams *params, char **headers,
char **residue)
{
static char buf[1024];
char buf[1024];
char **residue2=residue;
int ret;
if (name) {
@ -2009,7 +2009,11 @@ static int sip_uri_domain_cmp(const char *host1, const char *host2)
*/
if (!addr1_parsed) {
#ifdef HAVE_XLOCALE_H
return strcasecmp_l(host1, host2, c_locale);
if(!c_locale) {
return strcasecmp(host1, host2);
} else {
return strcasecmp_l(host1, host2, c_locale);
}
#else
return strcasecmp(host1, host2);
#endif

View File

@ -42,18 +42,19 @@
;static "<value>" => <column>
;alias <cdrvar> => <column>
alias start => calldate
alias callerid => clid
;alias src => src
;alias dst => dst
;alias dcontext => dcontext
;alias channel => channel
;alias dstchannel => dstchannel
;alias lastapp => lastapp
;alias lastdata => lastdata
;alias duration => duration
;alias billsec => billsec
;alias disposition => disposition
;alias amaflags => amaflags
;alias accountcode => accountcode
;alias userfield => userfield
;alias uniqueid => uniqueid
;alias clid => <a_field_not_named_clid>
;alias src => <a_field_not_named_src>
;alias dst => <a_field_not_named_dst>
;alias dcontext => <a_field_not_named_dcontext>
;alias channel => <a_field_not_named_channel>
;alias dstchannel => <a_field_not_named_dstchannel>
;alias lastapp => <a_field_not_named_lastapp>
;alias lastdata => <a_field_not_named_lastdata>
;alias duration => <a_field_not_named_duration>
;alias billsec => <a_field_not_named_billsec>
;alias disposition => <a_field_not_named_disposition>
;alias amaflags => <a_field_not_named_amaflags>
;alias accountcode => <a_field_not_named_accountcode>
;alias userfield => <a_field_not_named_userfield>
;alias uniqueid => <a_field_not_named_uniqueid>

View File

@ -63,6 +63,17 @@ bindaddr = 0.0.0.0
; debug = on ; enable some debugging info in AMI messages (default off).
; Also accessible through the "manager debug" CLI command.
; authtimeout specifies the maximum number of seconds a client has to
; authenticate. If the client does not authenticate beofre this timeout
; expires, the client will be disconnected. (default: 30 seconds)
;authtimeout = 30
; authlimit specifies the maximum number of unauthenticated sessions that will
; be allowed to connect at any given time.
;authlimit = 50
;httptimeout = 60
; a) httptimeout sets the Max-Age of the http cookie
; b) httptimeout is the amount of time the webserver waits

View File

@ -1020,7 +1020,7 @@ enum {
/*!
* \brief All softhangup flags.
*
* This can be used as an argument to ast_channel_softhangup_clear
* This can be used as an argument to ast_channel_clear_softhangup()
* to clear all softhangup flags from a channel.
*/
AST_SOFTHANGUP_ALL = (0xFFFFFFFF)

View File

@ -59,6 +59,13 @@
struct ast_dsp;
struct ast_dsp_busy_pattern {
/*! Number of elements. */
int length;
/*! Pattern elements in on/off time durations. */
int pattern[4];
};
enum threshold {
/* Array offsets */
THRESHOLD_SILENCE = 0,
@ -76,7 +83,7 @@ void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold);
void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences);
/*! \brief Set expected lengths of the busy tone */
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength);
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence);
/*! \brief Scans for progress indication in audio */
int ast_dsp_call_progress(struct ast_dsp *dsp, struct ast_frame *inf);

View File

@ -38,8 +38,9 @@ extern unsigned int ast_FD_SETSIZE;
#if !defined(HAVE_VARIABLE_FDSET) && defined(CONFIGURE_RAN_AS_ROOT)
#define ast_fdset fd_set
#else
#define ast_FDMAX 32768
typedef struct {
TYPEOF_FD_SET_FDS_BITS fds_bits[4096 / SIZEOF_FD_SET_FDS_BITS]; /* 32768 bits */
TYPEOF_FD_SET_FDS_BITS fds_bits[ast_FDMAX / 8 / SIZEOF_FD_SET_FDS_BITS]; /* 32768 bits */
} ast_fdset;
#undef FD_ZERO

View File

@ -3402,6 +3402,7 @@ int main(int argc, char *argv[])
fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
if (dup2(fd, fd2) < 0) {
ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
close(fd);
break;
}
@ -3410,9 +3411,12 @@ int main(int argc, char *argv[])
if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
}
ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
close(fd);
close(fd2);
} while (0);
#elif defined(HAVE_VARIABLE_FDSET)
ast_FD_SETSIZE = l.rlim_cur;
ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
#endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))

View File

@ -48,6 +48,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<description>
<para>Request call completion service for a previously failed
call attempt.</para>
<para>This application sets the following channel variables:</para>
<variablelist>
<variable name="CC_REQUEST_RESULT">
<para>This is the returned status of the request.</para>
<value name="SUCCESS" />
<value name="FAIL" />
</variable>
<variable name="CC_REQUEST_REASON">
<para>This is the reason the request failed.</para>
<value name="NO_CORE_INSTANCE" />
<value name="NOT_GENERIC" />
<value name="TOO_MANY_REQUESTS" />
<value name="UNSPECIFIED" />
</variable>
</variablelist>
</description>
</application>
<application name="CallCompletionCancel" language="en_US">
@ -57,6 +72,20 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<syntax />
<description>
<para>Cancel a Call Completion Request.</para>
<para>This application sets the following channel variables:</para>
<variablelist>
<variable name="CC_CANCEL_RESULT">
<para>This is the returned status of the cancel.</para>
<value name="SUCCESS" />
<value name="FAIL" />
</variable>
<variable name="CC_CANCEL_REASON">
<para>This is the reason the cancel failed.</para>
<value name="NO_CORE_INSTANCE" />
<value name="NOT_GENERIC" />
<value name="UNSPECIFIED" />
</variable>
</variablelist>
</description>
</application>
***/
@ -3934,7 +3963,9 @@ static int ccreq_exec(struct ast_channel *chan, const char *data)
match_flags = MATCH_NO_REQUEST;
if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionRequest"))) {
ast_log_dynamic_level(cc_logger_level, "Couldn't find a core instance for caller %s\n", device_name);
return -1;
pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NO_CORE_INSTANCE");
return 0;
}
ast_log_dynamic_level(cc_logger_level, "Core %d: Found core_instance for caller %s\n",
@ -3944,6 +3975,7 @@ static int ccreq_exec(struct ast_channel *chan, const char *data)
ast_log_dynamic_level(cc_logger_level, "Core %d: CallCompletionRequest is only for generic agent types.\n",
core_instance->core_id);
pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "NOT_GENERIC");
cc_unref(core_instance, "Unref core_instance since CallCompletionRequest was called with native agent");
return 0;
}
@ -3953,14 +3985,19 @@ static int ccreq_exec(struct ast_channel *chan, const char *data)
core_instance->core_id);
ast_cc_failed(core_instance->core_id, "Too many CC requests\n");
pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", "FAIL");
pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "TOO_MANY_REQUESTS");
cc_unref(core_instance, "Unref core_instance since too many CC requests");
return 0;
}
res = ast_cc_agent_accept_request(core_instance->core_id, "CallCompletionRequest called by caller %s for core_id %d", device_name, core_instance->core_id);
pbx_builtin_setvar_helper(chan, "CC_REQUEST_RESULT", res ? "FAIL" : "SUCCESS");
if (res) {
pbx_builtin_setvar_helper(chan, "CC_REQUEST_REASON", "UNSPECIFIED");
}
cc_unref(core_instance, "Done with CallCompletionRequest");
return res;
return 0;
}
static const char *cccancel_app = "CallCompletionCancel";
@ -3976,19 +4013,27 @@ static int cccancel_exec(struct ast_channel *chan, const char *data)
match_flags = MATCH_REQUEST;
if (!(core_instance = ao2_t_callback_data(cc_core_instances, 0, match_agent, device_name, &match_flags, "Find core instance for CallCompletionCancel"))) {
ast_log(LOG_WARNING, "Cannot find CC transaction to cancel for caller %s\n", device_name);
return -1;
ast_log_dynamic_level(cc_logger_level, "Cannot find CC transaction to cancel for caller %s\n", device_name);
pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NO_CORE_INSTANCE");
return 0;
}
if (strcmp(core_instance->agent->callbacks->type, "generic")) {
ast_log(LOG_WARNING, "CallCompletionCancel may only be used for calles with a generic agent\n");
cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
return -1;
pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", "FAIL");
pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "NOT_GENERIC");
return 0;
}
res = ast_cc_failed(core_instance->core_id, "Call completion request Cancelled for core ID %d by caller %s",
core_instance->core_id, device_name);
cc_unref(core_instance, "Unref core instance found during CallCompletionCancel");
return res;
pbx_builtin_setvar_helper(chan, "CC_CANCEL_RESULT", res ? "FAIL" : "SUCCESS");
if (res) {
pbx_builtin_setvar_helper(chan, "CC_CANCEL_REASON", "UNSPECIFIED");
}
return 0;
}
struct count_monitors_cb_data {

View File

@ -378,8 +378,7 @@ struct ast_dsp {
int ringtimeout;
int busymaybe;
int busycount;
int busy_tonelength;
int busy_quietlength;
struct ast_dsp_busy_pattern busy_cadence;
int historicnoise[DSP_HISTORY];
int historicsilence[DSP_HISTORY];
goertzel_state_t freqs[7];
@ -1183,9 +1182,14 @@ int ast_dsp_busydetect(struct ast_dsp *dsp)
int avgsilence = 0, hitsilence = 0;
#endif
int avgtone = 0, hittone = 0;
if (!dsp->busymaybe) {
return res;
/* if we have a 4 length pattern, the way busymaybe is set doesn't help us. */
if (dsp->busy_cadence.length != 4) {
if (!dsp->busymaybe) {
return res;
}
}
for (x = DSP_HISTORY - dsp->busycount; x < DSP_HISTORY; x++) {
#ifndef BUSYDETECT_TONEONLY
avgsilence += dsp->historicsilence[x];
@ -1239,23 +1243,60 @@ int ast_dsp_busydetect(struct ast_dsp *dsp)
res = 1;
#endif
}
/* If we have a 4-length pattern, we can go ahead and just check it in a different way. */
if (dsp->busy_cadence.length == 4) {
int x;
int errors = 0;
int errors_max = ((4 * dsp->busycount) / 100.0) * BUSY_PAT_PERCENT;
for (x = DSP_HISTORY - (dsp->busycount); x < DSP_HISTORY; x += 2) {
int temp_error;
temp_error = abs(dsp->historicnoise[x] - dsp->busy_cadence.pattern[0]);
if ((temp_error * 100) / dsp->busy_cadence.pattern[0] > BUSY_PERCENT) {
errors++;
}
temp_error = abs(dsp->historicnoise[x + 1] - dsp->busy_cadence.pattern[2]);
if ((temp_error * 100) / dsp->busy_cadence.pattern[2] > BUSY_PERCENT) {
errors++;
}
temp_error = abs(dsp->historicsilence[x] - dsp->busy_cadence.pattern[1]);
if ((temp_error * 100) / dsp->busy_cadence.pattern[1] > BUSY_PERCENT) {
errors++;
}
temp_error = abs(dsp->historicsilence[x + 1] - dsp->busy_cadence.pattern[3]);
if ((temp_error * 100) / dsp->busy_cadence.pattern[3] > BUSY_PERCENT) {
errors++;
}
}
ast_debug(5, "errors = %d max = %d\n", errors, errors_max);
if (errors <= errors_max) {
return 1;
}
}
/* If we know the expected busy tone length, check we are in the range */
if (res && (dsp->busy_tonelength > 0)) {
if (abs(avgtone - dsp->busy_tonelength) > (dsp->busy_tonelength*BUSY_PAT_PERCENT/100)) {
if (res && (dsp->busy_cadence.pattern[0] > 0)) {
if (abs(avgtone - dsp->busy_cadence.pattern[0]) > (dsp->busy_cadence.pattern[0]*BUSY_PAT_PERCENT/100)) {
#ifdef BUSYDETECT_DEBUG
ast_debug(5, "busy detector: avgtone of %d not close enough to desired %d\n",
avgtone, dsp->busy_tonelength);
avgtone, dsp->busy_cadence.pattern[0]);
#endif
res = 0;
}
}
#ifndef BUSYDETECT_TONEONLY
/* If we know the expected busy tone silent-period length, check we are in the range */
if (res && (dsp->busy_quietlength > 0)) {
if (abs(avgsilence - dsp->busy_quietlength) > (dsp->busy_quietlength*BUSY_PAT_PERCENT/100)) {
if (res && (dsp->busy_cadence.pattern[1] > 0)) {
if (abs(avgsilence - dsp->busy_cadence.pattern[1]) > (dsp->busy_cadence.pattern[1] * BUSY_PAT_PERCENT / 100)) {
#ifdef BUSYDETECT_DEBUG
ast_debug(5, "busy detector: avgsilence of %d not close enough to desired %d\n",
avgsilence, dsp->busy_quietlength);
avgsilence, dsp->busy_cadence.pattern[1]);
#endif
res = 0;
}
@ -1571,11 +1612,10 @@ void ast_dsp_set_busy_count(struct ast_dsp *dsp, int cadences)
dsp->busycount = cadences;
}
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, int tonelength, int quietlength)
void ast_dsp_set_busy_pattern(struct ast_dsp *dsp, const struct ast_dsp_busy_pattern *cadence)
{
dsp->busy_tonelength = tonelength;
dsp->busy_quietlength = quietlength;
ast_debug(1, "dsp busy pattern set to %d,%d\n", tonelength, quietlength);
dsp->busy_cadence = *cadence;
ast_debug(1, "dsp busy pattern set to %d,%d,%d,%d\n", cadence->pattern[0], cadence->pattern[1], (cadence->length == 4) ? cadence->pattern[2] : 0, (cadence->length == 4) ? cadence->pattern[3] : 0);
}
void ast_dsp_digitreset(struct ast_dsp *dsp)

View File

@ -4857,6 +4857,17 @@ static int load_config(void)
"applicationmap"
};
/* Clear the existing parkinglots in the parkinglots container. */
{
struct ast_parkinglot *p;
struct ao2_iterator iter = ao2_iterator_init(parkinglots, 0);
while ((p = ao2_iterator_next(&iter))) {
ao2_unlink(parkinglots, p);
ao2_ref(p,-1);
}
ao2_iterator_destroy(&iter);
}
default_parkinglot = build_parkinglot(DEFAULT_PARKINGLOT, NULL);
if (default_parkinglot) {
ao2_lock(default_parkinglot);
@ -4906,7 +4917,19 @@ static int load_config(void)
ast_log(LOG_WARNING,"Could not load features.conf\n");
return 0;
}
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
if ((var = ast_variable_browse(cfg, "general"))) {
/* Find a general context in features.conf, we need to clear our existing default context */
/* Can't outright destroy the parking lot because it's needed in a little while. */
if ((con = ast_context_find(default_parkinglot->parking_con))) {
ast_context_destroy(con, registrar);
}
if ((con = ast_context_find(default_parkinglot->parking_con_dial))) {
ast_context_destroy(con, registrar);
}
}
for (; var; var = var->next) {
if (!strcasecmp(var->name, "parkext")) {
ast_copy_string(default_parkinglot->parkext, var->value, sizeof(default_parkinglot->parkext));
} else if (!strcasecmp(var->name, "context")) {

View File

@ -860,12 +860,15 @@ static int httptimeout = 60;
static int broken_events_action = 0;
static int manager_enabled = 0;
static int webmanager_enabled = 0;
static int authtimeout;
static int authlimit;
static char *manager_channelvars;
#define DEFAULT_REALM "asterisk"
static char global_realm[MAXHOSTNAMELEN]; /*!< Default realm */
static int block_sockets;
static int unauth_sessions = 0;
static int manager_debug; /*!< enable some debugging code in the manager */
@ -944,6 +947,7 @@ struct mansession_session {
int send_events; /*!< XXX what ? */
struct eventqent *last_ev; /*!< last event processed. */
int writetimeout; /*!< Timeout for ast_carefulwrite() */
time_t authstart;
int pending_event; /*!< Pending events indicator in case when waiting_thread is NULL */
time_t noncetime; /*!< Timer for nonce value expiration */
unsigned long oldnonce; /*!< Stale nonce value */
@ -2929,6 +2933,7 @@ static int action_login(struct mansession *s, const struct message *m)
return -1;
}
s->session->authenticated = 1;
ast_atomic_fetchadd_int(&unauth_sessions, -1);
if (manager_displayconnects(s->session)) {
ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
}
@ -4535,6 +4540,8 @@ static int get_input(struct mansession *s, char *output)
int res, x;
int maxlen = sizeof(s->session->inbuf) - 1;
char *src = s->session->inbuf;
int timeout = -1;
time_t now;
/*
* Look for \r\n within the buffer. If found, copy to the output
@ -4563,6 +4570,20 @@ static int get_input(struct mansession *s, char *output)
}
res = 0;
while (res == 0) {
/* calculate a timeout if we are not authenticated */
if (!s->session->authenticated) {
if(time(&now) == -1) {
ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
return -1;
}
timeout = (authtimeout - (now - s->session->authstart)) * 1000;
if (timeout < 0) {
/* we have timed out */
return 0;
}
}
ao2_lock(s->session);
if (s->session->pending_event) {
s->session->pending_event = 0;
@ -4572,7 +4593,7 @@ static int get_input(struct mansession *s, char *output)
s->session->waiting_thread = pthread_self();
ao2_unlock(s->session);
res = ast_wait_for_input(s->session->fd, -1); /* return 0 on timeout ? */
res = ast_wait_for_input(s->session->fd, timeout);
ao2_lock(s->session);
s->session->waiting_thread = AST_PTHREADT_NULL;
@ -4607,6 +4628,7 @@ static int do_message(struct mansession *s)
struct message m = { 0 };
char header_buf[sizeof(s->session->inbuf)] = { '\0' };
int res;
time_t now;
for (;;) {
/* Check if any events are pending and do them if needed */
@ -4615,6 +4637,19 @@ static int do_message(struct mansession *s)
}
res = get_input(s, header_buf);
if (res == 0) {
if (!s->session->authenticated) {
if(time(&now) == -1) {
ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
return -1;
}
if (now - s->session->authstart > authtimeout) {
if (displayconnects) {
ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
}
return -1;
}
}
continue;
} else if (res > 0) {
if (ast_strlen_zero(header_buf)) {
@ -4648,10 +4683,18 @@ static void *session_do(void *data)
struct sockaddr_in ser_remote_address_tmp;
struct protoent *p;
if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
fclose(ser->f);
ast_atomic_fetchadd_int(&unauth_sessions, -1);
goto done;
}
ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
session = build_mansession(ser_remote_address_tmp);
if (session == NULL) {
fclose(ser->f);
ast_atomic_fetchadd_int(&unauth_sessions, -1);
goto done;
}
@ -4690,7 +4733,15 @@ static void *session_do(void *data)
AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
if(time(&session->authstart) == -1) {
ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
ast_atomic_fetchadd_int(&unauth_sessions, -1);
ao2_unlock(session);
session_destroy(session);
goto done;
}
ao2_unlock(session);
astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */
for (;;) {
if ((res = do_message(&s)) < 0 || s.write_error) {
@ -4703,6 +4754,7 @@ static void *session_do(void *data)
ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
}
} else {
ast_atomic_fetchadd_int(&unauth_sessions, -1);
if (displayconnects) {
ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
}
@ -6212,6 +6264,8 @@ static int __init_manager(int reload)
displayconnects = 1;
broken_events_action = 0;
authtimeout = 30;
authlimit = 50;
if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n");
return 0;
@ -6273,6 +6327,22 @@ static int __init_manager(int reload)
manager_debug = ast_true(val);
} else if (!strcasecmp(var->name, "httptimeout")) {
newhttptimeout = atoi(val);
} else if (!strcasecmp(var->name, "authtimeout")) {
int timeout = atoi(var->value);
if (timeout < 1) {
ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value);
} else {
authtimeout = timeout;
}
} else if (!strcasecmp(var->name, "authlimit")) {
int limit = atoi(var->value);
if (limit < 1) {
ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value);
} else {
authlimit = limit;
}
} else if (!strcasecmp(var->name, "channelvars")) {
struct manager_channel_variable *mcv;
char *remaining = ast_strdupa(val), *next;

View File

@ -905,6 +905,7 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
int iprior = -2;
char *cidmatch, *app, *app_data;
char *start, *end;
const char *into_context;
switch (cmd) {
case CLI_INIT:
@ -968,10 +969,22 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
if (!exten || !prior || !app || (!app_data && iprior != PRIORITY_HINT))
return CLI_SHOWUSAGE;
into_context = a->argv[5];
if (!ast_context_find(into_context)) {
ast_cli(a->fd, "Context '%s' did not exist prior to add extension - the context will be created.\n", into_context);
}
if (!ast_context_find_or_create(NULL, NULL, into_context, registrar)) {
ast_cli(a->fd, "ast_context_find_or_create() failed\n");
ast_cli(a->fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n", exten, prior, app, app_data, into_context);
return CLI_FAILURE;
}
if (!app_data)
app_data="";
if (ast_add_extension(a->argv[5], a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
if (ast_add_extension(into_context, a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
(void *)strdup(app_data), ast_free_ptr, registrar)) {
switch (errno) {
case ENOMEM:
@ -983,17 +996,17 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
break;
case ENOENT:
ast_cli(a->fd, "No existence of '%s' context\n", a->argv[5]);
ast_cli(a->fd, "No existence of '%s' context\n", into_context);
break;
case EEXIST:
ast_cli(a->fd, "Extension %s@%s with priority %s already exists\n",
exten, a->argv[5], prior);
exten, into_context, prior);
break;
default:
ast_cli(a->fd, "Failed to add '%s,%s,%s,%s' extension into '%s' context\n",
exten, prior, app, app_data, a->argv[5]);
exten, prior, app, app_data, into_context);
break;
}
return CLI_FAILURE;
@ -1001,10 +1014,10 @@ static char *handle_cli_dialplan_add_extension(struct ast_cli_entry *e, int cmd,
if (a->argc == 7)
ast_cli(a->fd, "Extension %s@%s (%s) replace by '%s,%s,%s,%s'\n",
exten, a->argv[5], prior, exten, prior, app, app_data);
exten, into_context, prior, exten, prior, app, app_data);
else
ast_cli(a->fd, "Extension '%s,%s,%s,%s' added into '%s' context\n",
exten, prior, app, app_data, a->argv[5]);
exten, prior, app, app_data, into_context);
return CLI_SUCCESS;
}