Merge branch 'master' of 192.168.0.100:/repos/git/asterisk
This commit is contained in:
commit
2ac6b3ac85
14
CHANGES
14
CHANGES
|
@ -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 ----------------
|
||||
------------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2371
channels/sig_pri.c
2371
channels/sig_pri.c
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
57
main/ccss.c
57
main/ccss.c
|
@ -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 {
|
||||
|
|
68
main/dsp.c
68
main/dsp.c
|
@ -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)
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Reference in New Issue