diff options
48 files changed, 2261 insertions, 897 deletions
@@ -103,6 +103,19 @@ app_confbridge instance, allows a channel to immediately exit the ConfBridge without having to wait for a leave announcement to play. +app_dial +------------------ + * Added the "Q" option which sets the Q.850/Q.931 cause on unanswered channels + when another channel answers the call. The default of ANSWERED_ELSEWHERE + is unchanged. + +res_ari +------------------ + * ARI events will all now include a new field in the root of the JSON message, + 'asterisk_id'. This will be the unique ID for the Asterisk system + transmitting the event. The value can be overridden using the 'entityid' + setting in asterisk.conf. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 13 to Asterisk 14 -------------------- ------------------------------------------------------------------------------ @@ -99,6 +99,10 @@ export WGET_EXTRA_ARGS export LDCONFIG export LDCONFIG_FLAGS export PYTHON +export TAR +export PATCH +export SED +export NM # makeopts is required unless the goal is clean or distclean ifeq ($(findstring clean,$(MAKECMDGOALS)),) diff --git a/addons/res_config_mysql.c b/addons/res_config_mysql.c index c9fa7c744..e6b0e53c0 100644 --- a/addons/res_config_mysql.c +++ b/addons/res_config_mysql.c @@ -126,7 +126,6 @@ static char *handle_cli_realtime_mysql_status(struct ast_cli_entry *e, int cmd, static char *handle_cli_realtime_mysql_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a); static int load_mysql_config(struct ast_config *config, const char *category, struct mysql_conn *conn); static int require_mysql(const char *database, const char *tablename, va_list ap); -static int internal_require(const char *database, const char *table, ...) attribute_sentinel; static struct ast_cli_entry cli_realtime_mysql_status[] = { AST_CLI_DEFINE(handle_cli_realtime_mysql_status, "Shows connection information for the MySQL RealTime driver"), @@ -165,16 +164,6 @@ static struct mysql_conn *find_database(const char *database, int for_write) #define release_database(a) ast_mutex_unlock(&(a)->lock) -static int internal_require(const char *database, const char *table, ...) -{ - va_list ap; - int res; - va_start(ap, table); - res = require_mysql(database, table, ap); - va_end(ap); - return res; -} - static void destroy_table(struct tables *table) { struct columns *column; @@ -600,11 +589,6 @@ static int update_mysql(const char *database, const char *tablename, const char ESCAPE_STRING(buf, field->value); ast_str_set(&sql, 0, "UPDATE %s SET `%s` = '%s'", tablename, field->name, ast_str_buffer(buf)); - /* If the column length isn't long enough, give a chance to lengthen it. */ - if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) { - internal_require(database, tablename, field->name, RQ_CHAR, ast_str_strlen(buf), SENTINEL); - } - while ((field = field->next)) { /* If the column is not within the table, then skip it */ if (!(column = find_column(table, field->name))) { @@ -614,11 +598,6 @@ static int update_mysql(const char *database, const char *tablename, const char ESCAPE_STRING(buf, field->value); ast_str_append(&sql, 0, ", `%s` = '%s'", field->name, ast_str_buffer(buf)); - - /* If the column length isn't long enough, give a chance to lengthen it. */ - if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) { - internal_require(database, tablename, field->name, RQ_CHAR, ast_str_strlen(buf), SENTINEL); - } } ESCAPE_STRING(buf, lookup); @@ -703,11 +682,6 @@ static int update2_mysql(const char *database, const char *tablename, const stru ESCAPE_STRING(buf, field->value); ast_str_append(&where, 0, "%s `%s` = '%s'", first ? "" : " AND", field->name, ast_str_buffer(buf)); first = 0; - - /* If the column length isn't long enough, give a chance to lengthen it. */ - if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) { - internal_require(database, tablename, field->name, RQ_CHAR, ast_str_strlen(buf), SENTINEL); - } } first = 1; @@ -721,11 +695,6 @@ static int update2_mysql(const char *database, const char *tablename, const stru ESCAPE_STRING(buf, field->value); ast_str_append(&sql, 0, "%s `%s` = '%s'", first ? "" : ",", field->name, ast_str_buffer(buf)); first = 0; - - /* If the column length isn't long enough, give a chance to lengthen it. */ - if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) { - internal_require(database, tablename, field->name, RQ_CHAR, ast_str_strlen(buf), SENTINEL); - } } release_table(table); @@ -759,7 +728,6 @@ static int update2_mysql(const char *database, const char *tablename, const stru static int store_mysql(const char *database, const char *table, const struct ast_variable *rt_fields) { struct mysql_conn *dbh; - my_ulonglong insertid; struct ast_str *sql = ast_str_thread_get(&sql_buf, 16); struct ast_str *sql2 = ast_str_thread_get(&sql2_buf, 16); struct ast_str *buf = ast_str_thread_get(&scratch_buf, 16); @@ -792,15 +760,11 @@ static int store_mysql(const char *database, const char *table, const struct ast ast_str_set(&sql, 0, "INSERT INTO %s (`%s`", table, field->name); ast_str_set(&sql2, 0, ") VALUES ('%s'", ast_str_buffer(buf)); - internal_require(database, table, field->name, RQ_CHAR, ast_str_strlen(buf), SENTINEL); - while ((field = field->next)) { ESCAPE_STRING(buf, field->value); - if (internal_require(database, table, field->name, RQ_CHAR, ast_str_strlen(buf), SENTINEL) == 0) { - ast_str_append(&sql, 0, ", `%s`", field->name); - ast_str_append(&sql2, 0, ", '%s'", ast_str_buffer(buf)); - } + ast_str_append(&sql, 0, ", `%s`", field->name); + ast_str_append(&sql2, 0, ", '%s'", ast_str_buffer(buf)); } ast_str_append(&sql, 0, "%s)", ast_str_buffer(sql2)); ast_debug(1,"MySQL RealTime: Insert SQL: %s\n", ast_str_buffer(sql)); @@ -812,18 +776,11 @@ static int store_mysql(const char *database, const char *table, const struct ast return -1; } - /*!\note The return value is non-portable and may change in future versions. */ - insertid = mysql_insert_id(&dbh->handle); release_database(dbh); - ast_debug(1, "MySQL RealTime: row inserted on table: %s, id: %llu\n", table, insertid); + ast_debug(1, "MySQL RealTime: row inserted on table: %s\n", table); - /* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html - * An integer greater than zero indicates the number of rows affected - * Zero indicates that no records were updated - * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) - */ - return (int)insertid; + return 1; } static int destroy_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *rt_fields) @@ -989,105 +946,14 @@ static int unload_mysql(const char *database, const char *tablename) return cur ? 0 : -1; } -static int modify_mysql(const char *database, const char *tablename, struct columns *column, require_type type, int len) -{ - /*!\note Cannot use ANY of the same scratch space as is used in other functions, as this one is interspersed. */ - struct ast_str *sql = ast_str_thread_get(&modify_buf, 100), *escbuf = ast_str_thread_get(&modify2_buf, 100); - struct ast_str *typestr = ast_str_thread_get(&modify3_buf, 30); - int waschar = strncasecmp(column->type, "char", 4) == 0 ? 1 : 0; - int wasvarchar = strncasecmp(column->type, "varchar", 7) == 0 ? 1 : 0; - int res = 0; - struct mysql_conn *dbh; - - if (!(dbh = find_database(database, 1))) { - return -1; - } - - do { - if (type == RQ_CHAR || waschar || wasvarchar) { - if (wasvarchar) { - ast_str_set(&typestr, 0, "VARCHAR(%d)", len); - } else { - ast_str_set(&typestr, 0, "CHAR(%d)", len); - } - } else if (type == RQ_UINTEGER1) { - ast_str_set(&typestr, 0, "tinyint(3) unsigned"); - } else if (type == RQ_INTEGER1) { - ast_str_set(&typestr, 0, "tinyint(4)"); - } else if (type == RQ_UINTEGER2) { - ast_str_set(&typestr, 0, "smallint(5) unsigned"); - } else if (type == RQ_INTEGER2) { - ast_str_set(&typestr, 0, "smallint(6)"); - } else if (type == RQ_UINTEGER3) { - ast_str_set(&typestr, 0, "mediumint(8) unsigned"); - } else if (type == RQ_INTEGER3) { - ast_str_set(&typestr, 0, "mediumint(8)"); - } else if (type == RQ_UINTEGER4) { - ast_str_set(&typestr, 0, "int(10) unsigned"); - } else if (type == RQ_INTEGER4) { - ast_str_set(&typestr, 0, "int(11)"); - } else if (type == RQ_UINTEGER8) { - ast_str_set(&typestr, 0, "bigint(19) unsigned"); - } else if (type == RQ_INTEGER8) { - ast_str_set(&typestr, 0, "bigint(20)"); - } else if (type == RQ_DATETIME) { - ast_str_set(&typestr, 0, "datetime"); - } else if (type == RQ_DATE) { - ast_str_set(&typestr, 0, "date"); - } else if (type == RQ_FLOAT) { - ast_str_set(&typestr, 0, "FLOAT(%d,2)", len); - } else { - ast_log(LOG_ERROR, "Unknown type (should NEVER happen)\n"); - res = -1; - break; - } - ast_str_set(&sql, 0, "ALTER TABLE %s MODIFY `%s` %s", tablename, column->name, ast_str_buffer(typestr)); - if (!column->null) { - ast_str_append(&sql, 0, " NOT NULL"); - } - if (!ast_strlen_zero(column->dflt)) { - ESCAPE_STRING(escbuf, column->dflt); - ast_str_append(&sql, 0, " DEFAULT '%s'", ast_str_buffer(escbuf)); - } - - if (!mysql_reconnect(dbh)) { - ast_log(LOG_ERROR, "Unable to add column: %s\n", ast_str_buffer(sql)); - res = -1; - break; - } - - /* Execution. */ - if (mysql_real_query(&dbh->handle, ast_str_buffer(sql), ast_str_strlen(sql))) { - ast_log(LOG_WARNING, "MySQL RealTime: Failed to modify database: %s\n", mysql_error(&dbh->handle)); - ast_debug(1, "MySQL RealTime: Query: %s\n", ast_str_buffer(sql)); - res = -1; - } - } while (0); - - release_database(dbh); - return res; -} - -#define PICK_WHICH_ALTER_ACTION(stringtype) \ - if (table->database->requirements == RQ_WARN) { \ - ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ - "the required data length: %d (detected stringtype)\n", \ - tablename, database, column->name, size); \ - res = -1; \ - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { \ - table_altered = 1; \ - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { \ - table_altered = 1; \ - } else { \ - res = -1; \ - } - static int require_mysql(const char *database, const char *tablename, va_list ap) { struct columns *column; struct tables *table = find_table(database, tablename); char *elm; - int type, size, res = 0, table_altered = 0; + int type; + int size; + int res = 0; if (!table) { ast_log(LOG_WARNING, "Table %s not found in database. This table should exist if you're using realtime.\n", tablename); @@ -1097,55 +963,54 @@ static int require_mysql(const char *database, const char *tablename, va_list ap while ((elm = va_arg(ap, char *))) { type = va_arg(ap, require_type); size = va_arg(ap, int); + AST_LIST_TRAVERSE(&table->columns, column, list) { if (strcmp(column->name, elm) == 0) { /* Char can hold anything, as long as it is large enough */ if (strncmp(column->type, "char", 4) == 0 || strncmp(column->type, "varchar", 7) == 0) { if ((size > column->len) && column->len != -1) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Realtime table %s@%s: Column '%s' should be at least %d long, but is only %d long.\n", database, tablename, column->name, size, column->len); - res = -1; - } else if (modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else { - res = -1; - } + ast_log(LOG_WARNING, "Realtime table %s@%s: Column '%s' should be at least %d long, but is only %d long.\n", database, tablename, column->name, size, column->len); + res = -1; } } else if (strcasestr(column->type, "unsigned")) { if (!ast_rq_is_int(type)) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n", - database, tablename, column->name, column->type, - type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" : - type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : "a rather stiff drink"); - res = -1; - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { - table_altered = 1; - } else { - res = -1; - } + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n", + database, tablename, column->name, column->type, + type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" : + type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : "a rather stiff drink"); + res = -1; } else if (strncasecmp(column->type, "tinyint", 1) == 0) { if (type != RQ_UINTEGER1) { - PICK_WHICH_ALTER_ACTION(unsigned tinyint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "smallint", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2) { - PICK_WHICH_ALTER_ACTION(unsigned smallint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "mediumint", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2 && type != RQ_INTEGER2 && type != RQ_UINTEGER3) { - PICK_WHICH_ALTER_ACTION(unsigned mediumint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "int", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2 && type != RQ_INTEGER2 && type != RQ_UINTEGER3 && type != RQ_INTEGER3 && type != RQ_UINTEGER4) { - PICK_WHICH_ALTER_ACTION(unsigned int) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "bigint", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && @@ -1153,45 +1018,52 @@ static int require_mysql(const char *database, const char *tablename, va_list ap type != RQ_UINTEGER3 && type != RQ_INTEGER3 && type != RQ_UINTEGER4 && type != RQ_INTEGER4 && type != RQ_UINTEGER8) { - PICK_WHICH_ALTER_ACTION(unsigned bigint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } } else if (strcasestr(column->type, "int")) { if (!ast_rq_is_int(type)) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n", - database, tablename, column->name, column->type, - type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" : - type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : - "to get a life, rather than writing silly error messages"); - res = -1; - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { - table_altered = 1; - } else { - res = -1; - } + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' cannot be type '%s' (need %s)\n", + database, tablename, column->name, column->type, + type == RQ_CHAR ? "char" : type == RQ_FLOAT ? "float" : + type == RQ_DATETIME ? "datetime" : type == RQ_DATE ? "date" : + "to get a life, rather than writing silly error messages"); + res = -1; } else if (strncasecmp(column->type, "tinyint", 1) == 0) { if (type != RQ_INTEGER1) { - PICK_WHICH_ALTER_ACTION(tinyint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "smallint", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_INTEGER2) { - PICK_WHICH_ALTER_ACTION(smallint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "mediumint", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2 && type != RQ_INTEGER2 && type != RQ_INTEGER3) { - PICK_WHICH_ALTER_ACTION(mediumint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "int", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && type != RQ_UINTEGER2 && type != RQ_INTEGER2 && type != RQ_UINTEGER3 && type != RQ_INTEGER3 && type != RQ_INTEGER4) { - PICK_WHICH_ALTER_ACTION(int) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } else if (strncasecmp(column->type, "bigint", 1) == 0) { if (type != RQ_UINTEGER1 && type != RQ_INTEGER1 && @@ -1199,137 +1071,41 @@ static int require_mysql(const char *database, const char *tablename, va_list ap type != RQ_UINTEGER3 && type != RQ_INTEGER3 && type != RQ_UINTEGER4 && type != RQ_INTEGER4 && type != RQ_INTEGER8) { - PICK_WHICH_ALTER_ACTION(bigint) + ast_log(LOG_WARNING, "Realtime table %s@%s: column '%s' may not be large enough for " \ + "the required data length: %d (detected stringtype)\n", \ + tablename, database, column->name, size); \ + res = -1; \ } } } else if (strncmp(column->type, "float", 5) == 0) { if (!ast_rq_is_int(type) && type != RQ_FLOAT) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type); - res = -1; - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { - table_altered = 1; - } else { - res = -1; - } + ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type); + res = -1; } } else if (strncmp(column->type, "datetime", 8) == 0 || strncmp(column->type, "timestamp", 9) == 0) { if (type != RQ_DATETIME) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type); - res = -1; - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { - table_altered = 1; - } else { - res = -1; - } + ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type); + res = -1; } } else if (strncmp(column->type, "date", 4) == 0) { if (type != RQ_DATE) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type); - res = -1; - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { - table_altered = 1; - } else { - res = -1; - } - } - } else { /* Other, possibly unsupported types? */ - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name); + ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type); res = -1; - } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) { - table_altered = 1; - } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) { - table_altered = 1; - } else { } + } else { /* Other, possibly unsupported types? */ + ast_log(LOG_WARNING, "Possibly unsupported column type '%s' on column '%s'\n", column->type, column->name); + res = -1; } break; } } if (!column) { - if (table->database->requirements == RQ_WARN) { - ast_log(LOG_WARNING, "Table %s requires a column '%s' of size '%d', but no such column exists.\n", tablename, elm, size); - } else { - struct ast_str *sql = ast_str_thread_get(&modify_buf, 100), *fieldtype = ast_str_thread_get(&modify3_buf, 16); - - if (table->database->requirements == RQ_CREATECHAR || type == RQ_CHAR) { - ast_str_set(&fieldtype, 0, "CHAR(%d)", size); - } else if (type == RQ_UINTEGER1 || type == RQ_UINTEGER2 || type == RQ_UINTEGER3 || type == RQ_UINTEGER4 || type == RQ_UINTEGER8) { - if (type == RQ_UINTEGER1) { - ast_str_set(&fieldtype, 0, "TINYINT(3) UNSIGNED"); - } else if (type == RQ_UINTEGER2) { - ast_str_set(&fieldtype, 0, "SMALLINT(5) UNSIGNED"); - } else if (type == RQ_UINTEGER3) { - ast_str_set(&fieldtype, 0, "MEDIUMINT(8) UNSIGNED"); - } else if (type == RQ_UINTEGER4) { - ast_str_set(&fieldtype, 0, "INT(10) UNSIGNED"); - } else if (type == RQ_UINTEGER8) { - ast_str_set(&fieldtype, 0, "BIGINT(20) UNSIGNED"); - } else { - ast_log(LOG_WARNING, "Somebody should check this code for a rather large bug... it's about to squash Tokyo.\n"); - continue; - } - } else if (ast_rq_is_int(type)) { - if (type == RQ_INTEGER1) { - ast_str_set(&fieldtype, 0, "TINYINT(3)"); - } else if (type == RQ_INTEGER2) { - ast_str_set(&fieldtype, 0, "SMALLINT(5)"); - } else if (type == RQ_INTEGER3) { - ast_str_set(&fieldtype, 0, "MEDIUMINT(8)"); - } else if (type == RQ_INTEGER4) { - ast_str_set(&fieldtype, 0, "INT(10)"); - } else if (type == RQ_INTEGER8) { - ast_str_set(&fieldtype, 0, "BIGINT(20)"); - } else { - ast_log(LOG_WARNING, "Somebody should check this code for a rather large bug... it's about to eat Cincinnati.\n"); - continue; - } - } else if (type == RQ_FLOAT) { - ast_str_set(&fieldtype, 0, "FLOAT"); - } else if (type == RQ_DATE) { - ast_str_set(&fieldtype, 0, "DATE"); - } else if (type == RQ_DATETIME) { - ast_str_set(&fieldtype, 0, "DATETIME"); - } else { - continue; - } - ast_str_set(&sql, 0, "ALTER TABLE %s ADD COLUMN %s %s", tablename, elm, ast_str_buffer(fieldtype)); - - ast_mutex_lock(&table->database->lock); - if (!mysql_reconnect(table->database)) { - ast_mutex_unlock(&table->database->lock); - ast_log(LOG_ERROR, "Unable to add column: %s\n", ast_str_buffer(sql)); - continue; - } - - /* Execution. */ - if (mysql_real_query(&table->database->handle, ast_str_buffer(sql), ast_str_strlen(sql))) { - ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n"); - ast_debug(1, "MySQL RealTime: Query: %s\n", ast_str_buffer(sql)); - ast_debug(1, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&table->database->handle)); - } else { - table_altered = 1; - } - } + ast_log(LOG_WARNING, "Table %s requires a column '%s' of size '%d', but no such column exists.\n", tablename, elm, size); } } release_table(table); - /* If we altered the table, we must refresh the cache */ - if (table_altered) { - unload_mysql(database, tablename); - release_table(find_table(database, tablename)); - } return res; } diff --git a/apps/app_dial.c b/apps/app_dial.c index 316d38da1..b5d8f50c7 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -375,6 +375,25 @@ ASTERISK_REGISTER_FILE() <para>Enable privacy mode. Use <replaceable>x</replaceable> as the family/key in the AstDB database if it is provided. The current extension is used if a database family/key is not specified.</para> </option> + <option name="Q"> + <argument name="cause" required="true"/> + <para>Specify the Q.850/Q.931 <replaceable>cause</replaceable> to send on + unanswered channels when another channel answers the call. + As with <literal>Hangup()</literal>, <replaceable>cause</replaceable> + can be a numeric cause code or a name such as + <literal>NO_ANSWER</literal>, + <literal>USER_BUSY</literal>, + <literal>CALL_REJECTED</literal> or + <literal>ANSWERED_ELSEWHERE</literal> (the default if Q isn't specified). + You can also specify <literal>0</literal> or <literal>NONE</literal> + to send no cause. See the <filename>causes.h</filename> file for the + full list of valid causes and names. + </para> + <note> + <para>chan_sip does not support setting the cause on a CANCEL to anything + other than ANSWERED_ELSEWHERE.</para> + </note> + </option> <option name="r"> <para>Default: Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling party until the called channel has answered.</para> @@ -520,6 +539,9 @@ ASTERISK_REGISTER_FILE() <example title="Dial with call length limit"> same => n,Dial(PJSIP/alice,,L(60000:30000:10000)) </example> + <example title="Dial alice and bob and send NO_ANSWER to bob instead of ANSWERED_ELSEWHERE when alice answers"> + same => n,Dial(PJSIP/alice&PJSIP/bob,,Q(NO_ANSWER)) + </example> <example title="Dial with pre-dial subroutines"> [default] @@ -684,6 +706,7 @@ enum { #define OPT_PREDIAL_CALLEE (1LLU << 41) #define OPT_PREDIAL_CALLER (1LLU << 42) #define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43) +#define OPT_HANGUPCAUSE (1LLU << 44) enum { OPT_ARG_ANNOUNCE = 0, @@ -705,6 +728,7 @@ enum { OPT_ARG_FORCE_CID_PRES, OPT_ARG_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLER, + OPT_ARG_HANGUPCAUSE, /* note: this entry _MUST_ be the last one in the enum */ OPT_ARG_ARRAY_SIZE }; @@ -738,6 +762,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE), AST_APP_OPTION('p', OPT_SCREENING), AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY), + AST_APP_OPTION_ARG('Q', OPT_HANGUPCAUSE, OPT_ARG_HANGUPCAUSE), AST_APP_OPTION_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK), AST_APP_OPTION('R', OPT_RING_WITH_EARLY_MEDIA), AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP), @@ -796,7 +821,7 @@ static void chanlist_free(struct chanlist *outgoing) ast_free(outgoing); } -static void hanguptree(struct dial_head *out_chans, struct ast_channel *exception, int answered_elsewhere) +static void hanguptree(struct dial_head *out_chans, struct ast_channel *exception, int hangupcause) { /* Hang up a tree of stuff */ struct chanlist *outgoing; @@ -804,9 +829,9 @@ static void hanguptree(struct dial_head *out_chans, struct ast_channel *exceptio while ((outgoing = AST_LIST_REMOVE_HEAD(out_chans, node))) { /* Hangup any existing lines we have open */ if (outgoing->chan && (outgoing->chan != exception)) { - if (answered_elsewhere) { + if (hangupcause >= 0) { /* This is for the channel drivers */ - ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE); + ast_channel_hangupcause_set(outgoing->chan, hangupcause); } ast_hangup(outgoing->chan); } @@ -2768,6 +2793,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast } else { const char *number; int dial_end_raised = 0; + int cause = -1; if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) ast_answer(chan); @@ -2778,7 +2804,23 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast /* Ah ha! Someone answered within the desired timeframe. Of course after this we will always return with -1 so that it is hung up properly after the conversation. */ - hanguptree(&out_chans, peer, 1); + + if (ast_test_flag64(&opts, OPT_HANGUPCAUSE) + && !ast_strlen_zero(opt_args[OPT_ARG_HANGUPCAUSE])) { + cause = ast_str2cause(opt_args[OPT_ARG_HANGUPCAUSE]); + if (cause <= 0) { + if (!strcasecmp(opt_args[OPT_ARG_HANGUPCAUSE], "NONE")) { + cause = 0; + } else if (sscanf(opt_args[OPT_ARG_HANGUPCAUSE], "%30d", &cause) != 1 + || cause < 0) { + ast_log(LOG_WARNING, "Invalid cause given to Dial(...Q(<cause>)): \"%s\"\n", + opt_args[OPT_ARG_HANGUPCAUSE]); + cause = -1; + } + } + } + hanguptree(&out_chans, peer, cause >= 0 ? cause : AST_CAUSE_ANSWERED_ELSEWHERE); + /* If appropriate, log that we have a destination channel and set the answer time */ if (ast_channel_name(peer)) pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer)); @@ -3182,7 +3224,11 @@ out: } ast_channel_early_bridge(chan, NULL); - hanguptree(&out_chans, NULL, ast_channel_hangupcause(chan)==AST_CAUSE_ANSWERED_ELSEWHERE || ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0 ); /* forward 'answered elsewhere' if we received it */ + /* forward 'answered elsewhere' if we received it */ + hanguptree(&out_chans, NULL, + ast_channel_hangupcause(chan) == AST_CAUSE_ANSWERED_ELSEWHERE + || ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) + ? AST_CAUSE_ANSWERED_ELSEWHERE : -1); pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status); diff --git a/apps/app_fax.c b/apps/app_fax.c index bf57d827d..6e174d4a7 100644 --- a/apps/app_fax.c +++ b/apps/app_fax.c @@ -262,13 +262,13 @@ static void phase_e_handler(t30_state_t *f, void *user_data, int result) } ast_json_ref(json_filenames); json_object = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: i, s: o}", - "type", s->direction ? "send" : "receive", - "remote_station_id", far_ident, - "local_station_id", local_ident, - "fax_pages", pages_transferred, - "fax_resolution", stat.y_resolution, - "fax_bitrate", stat.bit_rate, - "filenames", json_filenames); + "type", s->direction ? "send" : "receive", + "remote_station_id", AST_JSON_UTF8_VALIDATE(far_ident), + "local_station_id", AST_JSON_UTF8_VALIDATE(local_ident), + "fax_pages", pages_transferred, + "fax_resolution", stat.y_resolution, + "fax_bitrate", stat.bit_rate, + "filenames", json_filenames); message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(s->chan), ast_channel_fax_type(), json_object); if (!message) { return; diff --git a/apps/app_minivm.c b/apps/app_minivm.c index e97150b13..c84b7d7dd 100644 --- a/apps/app_minivm.c +++ b/apps/app_minivm.c @@ -1853,10 +1853,10 @@ static int notify_new_message(struct ast_channel *chan, const char *templatename } mwi_state->snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)); - json_object = ast_json_pack("{s: s, s: s}", - "Event", "MiniVoiceMail" - "Action", "SentNotification", - "Counter", counter); + json_object = ast_json_pack("{s: s, s: s, s: s}", + "Event", "MiniVoiceMail", + "Action", "SentNotification", + "Counter", counter ?: ""); if (!json_object) { goto notify_cleanup; } diff --git a/apps/app_queue.c b/apps/app_queue.c index a023b88ed..51741d374 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -2671,6 +2671,9 @@ static void init_queue(struct call_queue *q) q->retry = DEFAULT_RETRY; q->timeout = DEFAULT_TIMEOUT; q->maxlen = 0; + + ast_string_field_set(q, context, ""); + q->announcefrequency = 0; q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY; q->announceholdtime = 1; @@ -5645,12 +5648,12 @@ static void send_agent_complete(const char *queuename, struct ast_channel_snapsh } blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: s}", - "Queue", queuename, - "Interface", member->interface, - "MemberName", member->membername, - "HoldTime", (long)(callstart - holdstart), - "TalkTime", (long)(time(NULL) - callstart), - "Reason", reason); + "Queue", queuename, + "Interface", member->interface, + "MemberName", member->membername, + "HoldTime", (long)(callstart - holdstart), + "TalkTime", (long)(time(NULL) - callstart), + "Reason", reason ?: ""); queue_publish_multi_channel_snapshot_blob(ast_queue_topic(queuename), caller, peer, queue_agent_complete_type(), blob); @@ -7232,12 +7235,12 @@ static void set_queue_member_pause(struct call_queue *q, struct member *mem, con mem->paused = paused; if (paused) { - if (!ast_strlen_zero(reason)) { - ast_copy_string(mem->reason_paused, reason, sizeof(mem->reason_paused)); - } time(&mem->lastpause); /* update last pause field */ + } + if (paused && !ast_strlen_zero(reason)) { + ast_copy_string(mem->reason_paused, reason, sizeof(mem->reason_paused)); } else { - ast_copy_string(mem->reason_paused, "", sizeof(mem->reason_paused)); + mem->reason_paused[0] = '\0'; } ast_devstate_changed(mem->paused ? QUEUE_PAUSED_DEVSTATE : QUEUE_UNPAUSED_DEVSTATE, diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c index 69d6f69ea..6f8510552 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -284,6 +284,13 @@ ASTERISK_REGISTER_FILE() or 80. </para></description> </configOption> + <configOption name="binaural_active"> + <synopsis>If true binaural conferencing with stereo audio is active</synopsis> + <description><para> + Activates binaural mixing for a conference bridge. + Binaural features are disabled by default. + </para></description> + </configOption> <configOption name="record_conference"> <synopsis>Record the conference starting with the first active user's entrance and ending with the last active user's exit</synopsis> <description><para> @@ -2172,6 +2179,7 @@ int conf_load_config(void) aco_option_register(&cfg_info, "jitterbuffer", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), USER_OPT_JITTERBUFFER); /* "auto" will fail to parse as a uint, but we use PARSE_DEFAULT to set the value to 0 in that case, which is the value that auto resolves to */ aco_option_register(&cfg_info, "internal_sample_rate", ACO_EXACT, bridge_types, "0", OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct bridge_profile, internal_sample_rate), 0); + aco_option_register(&cfg_info, "binaural_active", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_BINAURAL_ACTIVE); aco_option_register_custom(&cfg_info, "mixing_interval", ACO_EXACT, bridge_types, "20", mix_interval_handler, 0); aco_option_register(&cfg_info, "record_conference", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_RECORD_CONFERENCE); aco_option_register_custom(&cfg_info, "video_mode", ACO_EXACT, bridge_types, NULL, video_mode_handler, 0); diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h index 93cac3a72..f91f2dc89 100644 --- a/apps/confbridge/include/confbridge.h +++ b/apps/confbridge/include/confbridge.h @@ -71,6 +71,7 @@ enum bridge_profile_flags { BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER = (1 << 3), /*!< Set if conference set the video feed to follow the loudest talker. */ BRIDGE_OPT_RECORD_FILE_APPEND = (1 << 4), /*!< Set if the record file should be appended to between start/stops. */ BRIDGE_OPT_RECORD_FILE_TIMESTAMP = (1 << 5), /*< Set if the record file should have a timestamp appended */ + BRIDGE_OPT_BINAURAL_ACTIVE = (1 << 6), /*< Set if binaural convolution is activated */ }; enum conf_menu_action_id { diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in index 9b077680e..9f1aa7082 100644 --- a/build_tools/menuselect-deps.in +++ b/build_tools/menuselect-deps.in @@ -54,6 +54,7 @@ PORTAUDIO=@PBX_PORTAUDIO@ PRI=@PBX_PRI@ OPENR2=@PBX_OPENR2@ RESAMPLE=@PBX_RESAMPLE@ +FFTW3=@PBX_FFTW3@ RADIUS=@PBX_RADIUS@ LAUNCHD=@PBX_LAUNCHD@ SPANDSP=@PBX_SPANDSP@ diff --git a/channels/chan_rtp.c b/channels/chan_rtp.c index 0fe66bd20..f1f4f05b9 100644 --- a/channels/chan_rtp.c +++ b/channels/chan_rtp.c @@ -314,7 +314,7 @@ static struct ast_channel *unicast_rtp_request(const char *type, struct ast_form } engine_name = S_COR(ast_test_flag(&opts, OPT_RTP_ENGINE), - opt_args[OPT_ARG_RTP_ENGINE], NULL); + opt_args[OPT_ARG_RTP_ENGINE], "asterisk"); ast_ouraddrfor(&address, &local_address); instance = ast_rtp_instance_new(engine_name, NULL, &local_address, NULL); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index d8a3d5c7a..40ef6409a 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8153,12 +8153,17 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit We also check for vrtp. If it's not there, we are not allowed do any video anyway. */ if (i->vrtp) { - if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT)) + if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS)) needvideo = 1; else if (ast_format_cap_count(i->prefcaps)) needvideo = ast_format_cap_has_type(i->prefcaps, AST_MEDIA_TYPE_VIDEO); /* Outbound call */ else needvideo = ast_format_cap_has_type(i->jointcaps, AST_MEDIA_TYPE_VIDEO); /* Inbound call */ + + if (!needvideo) { + ast_rtp_instance_destroy(i->vrtp); + i->vrtp = NULL; + } } if (i->trtp) { diff --git a/configs/samples/calendar.conf.sample b/configs/samples/calendar.conf.sample index 82b8702f0..d87b3b2c4 100644 --- a/configs/samples/calendar.conf.sample +++ b/configs/samples/calendar.conf.sample @@ -6,6 +6,8 @@ ;refresh = 15 ; refresh calendar every n minutes ;timeframe = 60 ; number of minutes of calendar data to pull for each refresh period ; ; should always be >= refresh +;fetch_again_at_reload = no ; to reload the calendar content when the module is reloaded +; ; ; You can set up res_calendar to execute a call upon an upcoming busy status ; The following fields are available from the ${CALENDAR_EVENT(<field>)} dialplan function: @@ -827,8 +827,6 @@ PBX_SPANDSP SPANDSP_DIR SPANDSP_INCLUDE SPANDSP_LIB -EXTERNALS_CACHE_DIR -SOUNDS_CACHE_DIR PBX_SDL_IMAGE SDL_IMAGE_DIR SDL_IMAGE_INCLUDE @@ -841,6 +839,10 @@ PBX_RESAMPLE RESAMPLE_DIR RESAMPLE_INCLUDE RESAMPLE_LIB +PBX_FFTW3 +FFTW3_DIR +FFTW3_INCLUDE +FFTW3_LIB PBX_RADIUS RADIUS_DIR RADIUS_INCLUDE @@ -977,11 +979,6 @@ PBX_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_DIR PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_INCLUDE PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_LIB -PJPROJECT_BUNDLED -PBX_PJPROJECT -PJPROJECT_DIR -PJPROJECT_INCLUDE -PJPROJECT_LIB PBX_PGSQL PGSQL_DIR PGSQL_INCLUDE @@ -1198,11 +1195,18 @@ PBX_ALSA ALSA_DIR ALSA_INCLUDE ALSA_LIB +PJPROJECT_INCLUDE +PJPROJECT_LIB +PBX_PJPROJECT +PJPROJECT_DIR +PJPROJECT_BUNDLED AST_C_COMPILER_FAMILY AST_CLANG_BLOCKS AST_CLANG_BLOCKS_LIBS AST_NESTED_FUNCTIONS AST_CODE_COVERAGE +EXTERNALS_CACHE_DIR +SOUNDS_CACHE_DIR AST_DEVMODE_STRICT AST_DEVMODE NOISY_BUILD @@ -1219,8 +1223,13 @@ PBX_BISON OPENSSL SHA1SUM LDCONFIG +DOWNLOAD_TO_STDOUT DOWNLOAD FETCH +NM +PATCH +TAR +BZIP2 ALEMBIC GIT BASH @@ -1350,7 +1359,10 @@ ac_user_opts=' enable_option_checking with_gnu_ld enable_dev_mode +with_sounds_cache +with_externals_cache enable_coverage +with_pjproject_bundled with_asound with_bfd with_execinfo @@ -1402,17 +1414,15 @@ with_osptk with_oss with_postgres with_pjproject -with_pjproject_bundled with_popt with_portaudio with_pri with_pwlib with_radius +with_fftw3 with_resample with_sdl with_SDL_image -with_sounds_cache -with_externals_cache with_spandsp with_ss7 with_speex @@ -2105,6 +2115,12 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sounds-cache=PATH + use cached sound tarfiles in PATH + --with-externals-cache=PATH + use cached external module tarfiles in PATH + --with-pjproject-bundled + Use bundled pjproject libraries --with-asound=PATH use Advanced Linux Sound Architecture files in PATH --with-bfd=PATH use Debug symbol decoding files in PATH --with-execinfo=PATH use Stack Backtrace files in PATH @@ -2160,20 +2176,15 @@ Optional Packages: --with-oss=PATH use Open Sound System files in PATH --with-postgres=PATH use PostgreSQL files in PATH --with-pjproject=PATH use PJPROJECT files in PATH - --with-pjproject-bundled - Use bundled pjproject libraries --with-popt=PATH use popt files in PATH --with-portaudio=PATH use PortAudio files in PATH --with-pri=PATH use ISDN PRI files in PATH --with-pwlib=PATH use PWlib files in PATH --with-radius=PATH use Radius Client files in PATH + --with-fftw3=PATH use LIBFFTW3 files in PATH --with-resample=PATH use LIBRESAMPLE files in PATH --with-sdl=PATH use Sdl files in PATH --with-SDL_image=PATH use Sdl Image files in PATH - --with-sounds-cache=PATH - use cached sound tarfiles in PATH - --with-externals-cache=PATH - use cached external module tarfiles in PATH --with-spandsp=PATH use SPANDSP files in PATH --with-ss7=PATH use ISDN SS7 files in PATH --with-speex=PATH use Speex files in PATH @@ -7646,10 +7657,218 @@ $as_echo "no" >&6; } fi +# Extract the first word of "bzip2", so it can be a program name with args. +set dummy bzip2; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_BZIP2+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $BZIP2 in + [\\/]* | ?:[\\/]*) + ac_cv_path_BZIP2="$BZIP2" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BZIP2="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_BZIP2" && ac_cv_path_BZIP2=":" + ;; +esac +fi +BZIP2=$ac_cv_path_BZIP2 +if test -n "$BZIP2"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BZIP2" >&5 +$as_echo "$BZIP2" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "tar", so it can be a program name with args. +set dummy tar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_TAR+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $TAR in + [\\/]* | ?:[\\/]*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TAR" && ac_cv_path_TAR=":" + ;; +esac +fi +TAR=$ac_cv_path_TAR +if test -n "$TAR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TAR" >&5 +$as_echo "$TAR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "patch", so it can be a program name with args. +set dummy patch; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATCH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PATCH in + [\\/]* | ?:[\\/]*) + ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PATCH" && ac_cv_path_PATCH=":" + ;; +esac +fi +PATCH=$ac_cv_path_PATCH +if test -n "$PATCH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5 +$as_echo "$PATCH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SED in + [\\/]* | ?:[\\/]*) + ac_cv_path_SED="$SED" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SED" && ac_cv_path_SED=":" + ;; +esac +fi +SED=$ac_cv_path_SED +if test -n "$SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 +$as_echo "$SED" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "nm", so it can be a program name with args. +set dummy nm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $NM in + [\\/]* | ?:[\\/]*) + ac_cv_path_NM="$NM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_NM="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_NM" && ac_cv_path_NM=":" + ;; +esac +fi +NM=$ac_cv_path_NM +if test -n "$NM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5 +$as_echo "$NM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "${WGET}" != ":" ; then DOWNLOAD=${WGET} + DOWNLOAD_TO_STDOUT="${WGET} -O-" else if test "${CURL}" != ":" ; then DOWNLOAD="${CURL} -O --progress-bar -w \"%{url_effective}\n\"" + DOWNLOAD_TO_STDOUT="${CURL} -L --progress-bar -w \"%{url_effective}\n\"" else # Extract the first word of "fetch", so it can be a program name with args. set dummy fetch; ac_word=$2 @@ -7693,9 +7912,12 @@ fi DOWNLOAD=${FETCH} + DOWNLOAD_TO_STDOUT="${FETCH} -o-" fi fi + + # Extract the first word of "ldconfig", so it can be a program name with args. set dummy ldconfig; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -8769,6 +8991,55 @@ fi + + +# Check whether --with-sounds-cache was given. +if test "${with_sounds_cache+set}" = set; then : + withval=$with_sounds_cache; + case ${withval} in + n|no) + unset SOUNDS_CACHE_DIR + ;; + *) + if test "x${withval}" = "x"; then + : + else + SOUNDS_CACHE_DIR="${withval}" + fi + ;; + esac + +else + : +fi + + + + + +# Check whether --with-externals-cache was given. +if test "${with_externals_cache+set}" = set; then : + withval=$with_externals_cache; + case ${withval} in + n|no) + unset EXTERNALS_CACHE_DIR + ;; + *) + if test "x${withval}" = "x"; then + : + else + EXTERNALS_CACHE_DIR="${withval}" + fi + ;; + esac + +else + : +fi + + + + AST_CODE_COVERAGE=no # Check whether --enable-coverage was given. if test "${enable_coverage+set}" = set; then : @@ -8921,6 +9192,118 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" +PJPROJECT_BUNDLED=no + + + +# Check whether --with-pjproject-bundled was given. +if test "${with_pjproject_bundled+set}" = set; then : + withval=$with_pjproject_bundled; case "${enableval}" in + n|no) PJPROJECT_BUNDLED=no ;; + *) PJPROJECT_BUNDLED=yes ;; + esac +fi + + + + + if test "$PJPROJECT_BUNDLED" = "yes" ; then + + if test "${ac_mandatory_list#*PJPROJECT*}" != "$ac_mandatory_list" ; then + as_fn_error $? "--with-pjproject and --with-pjproject-bundled can't both be specified" "$LINENO" 5 + fi + + ac_mandatory_list="$ac_mandatory_list PJPROJECT" + PJPROJECT_DIR="${ac_top_build_prefix}third-party/pjproject" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for embedded pjproject (may have to download)" >&5 +$as_echo_n "checking for embedded pjproject (may have to download)... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring" >&5 +$as_echo "configuring" >&6; } + + if test "x${DOWNLOAD_TO_STDOUT}" = "x" ; then + as_fn_error $? "A download utility (wget, curl or fetch) is required to download bundled pjproject" "$LINENO" 5 + fi + if test "${BZIP2}" = ":" ; then + as_fn_error $? "bzip2 is required to extract the pjproject tar file" "$LINENO" 5 + fi + if test "${TAR}" = ":" ; then + as_fn_error $? "tar is required to extract the pjproject tar file" "$LINENO" 5 + fi + if test "${PATCH}" = ":" ; then + as_fn_error $? "patch is required to configure bundled pjproject" "$LINENO" 5 + fi + if test "${SED}" = ":" ; then + as_fn_error $? "sed is required to configure bundled pjproject" "$LINENO" 5 + fi + if test "${NM}" = ":" ; then + as_fn_error $? "nm is required to build bundled pjproject" "$LINENO" 5 + fi + + export TAR PATCH SED NM EXTERNALS_CACHE_DIR DOWNLOAD_TO_STDOUT + ${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} configure + if test $? -ne 0 ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: Unable to configure ${PJPROJECT_DIR}" >&5 +$as_echo "$as_me: Unable to configure ${PJPROJECT_DIR}" >&6;} + as_fn_error $? "Run \"${GNU_MAKE} -C ${PJPROJECT_DIR} NOISY_BUILD=yes configure\" to see error details." "$LINENO" 5 + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bundled pjproject" >&5 +$as_echo_n "checking for bundled pjproject... " >&6; } + + PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} echo_cflags) + PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE" + PBX_PJPROJECT=1 + + +$as_echo "#define HAVE_PJPROJECT 1" >>confdefs.h + + +$as_echo "#define HAVE_PJPROJECT_BUNDLED 1" >>confdefs.h + + + +$as_echo "#define HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK 1" >>confdefs.h + + +$as_echo "#define HAVE_PJ_TRANSACTION_GRP_LOCK 1" >>confdefs.h + + +$as_echo "#define HAVE_PJSIP_REPLACE_MEDIA_STREAM 1" >>confdefs.h + + +$as_echo "#define HAVE_PJSIP_GET_DEST_INFO 1" >>confdefs.h + + +$as_echo "#define HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2 1" >>confdefs.h + + +$as_echo "#define HAVE_PJSIP_EXTERNAL_RESOLVER 1" >>confdefs.h + + +$as_echo "#define HAVE_PJSIP_TLS_TRANSPORT_PROTO 1" >>confdefs.h + + +$as_echo "#define HAVE_PJSIP_EVSUB_GRP_LOCK 1" >>confdefs.h + + +$as_echo "#define HAVE_PJSIP_INV_SESSION_REF 1" >>confdefs.h + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + fi + + + # AST_EXT_LIB_SETUP is used to tell configure to handle variables for # various packages. # $1 is the prefix for the variables in makeopts and autoconfig.h @@ -10938,6 +11321,7 @@ fi +if test "x${PBX_PJPROJECT}" != "x1" ; then PJPROJECT_DESCRIP="PJPROJECT" PJPROJECT_OPTION="pjproject" @@ -10970,29 +11354,6 @@ fi -PJPROJECT_BUNDLED=no - - - -# Check whether --with-pjproject-bundled was given. -if test "${with_pjproject_bundled+set}" = set; then : - withval=$with_pjproject_bundled; case "${enableval}" in - n|no) PJPROJECT_BUNDLED=no ;; - *) PJPROJECT_BUNDLED=yes ;; - esac -fi - - - -if test "$PJPROJECT_BUNDLED" = "yes" -a "${ac_mandatory_list#*PJPROJECT*}" != "$ac_mandatory_list" ; then - as_fn_error $? "--with-pjproject and --with-pjproject-bundled can't both be specified" "$LINENO" 5 -fi - -if test "$PJPROJECT_BUNDLED" = "yes" ; then - ac_mandatory_list="$ac_mandatory_list PJPROJECT" - PJPROJECT_DIR="${ac_top_build_prefix}third-party/pjproject" -fi - PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_DESCRIP="PJSIP Dialog Create UAS with Incremented Lock" PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_OPTION=pjsip @@ -11101,6 +11462,7 @@ PBX_PJSIP_INV_SESSION_REF=0 +fi POPT_DESCRIP="popt" @@ -11507,6 +11869,38 @@ fi + FFTW3_DESCRIP="LIBFFTW3" + FFTW3_OPTION="fftw3" + PBX_FFTW3=0 + +# Check whether --with-fftw3 was given. +if test "${with_fftw3+set}" = set; then : + withval=$with_fftw3; + case ${withval} in + n|no) + USE_FFTW3=no + # -1 is a magic value used by menuselect to know that the package + # was disabled, other than 'not found' + PBX_FFTW3=-1 + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} FFTW3" + ;; + *) + FFTW3_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} FFTW3" + ;; + esac + +fi + + + + + + + + RESAMPLE_DESCRIP="LIBRESAMPLE" RESAMPLE_OPTION="resample" PBX_RESAMPLE=0 @@ -11603,54 +11997,6 @@ fi - -# Check whether --with-sounds-cache was given. -if test "${with_sounds_cache+set}" = set; then : - withval=$with_sounds_cache; - case ${withval} in - n|no) - unset SOUNDS_CACHE_DIR - ;; - *) - if test "x${withval}" = "x"; then - : - else - SOUNDS_CACHE_DIR="${withval}" - fi - ;; - esac - -else - : -fi - - - - - -# Check whether --with-externals-cache was given. -if test "${with_externals_cache+set}" = set; then : - withval=$with_externals_cache; - case ${withval} in - n|no) - unset EXTERNALS_CACHE_DIR - ;; - *) - if test "x${withval}" = "x"; then - : - else - EXTERNALS_CACHE_DIR="${withval}" - fi - ;; - esac - -else - : -fi - - - - SPANDSP_DESCRIP="SPANDSP" SPANDSP_OPTION="spandsp" PBX_SPANDSP=0 @@ -25153,251 +25499,7 @@ $as_echo "$as_me: *** including --without-postgres" >&6;} fi if test "$USE_PJPROJECT" != "no" ; then - if test "$PJPROJECT_BUNDLED" = "yes" ; then - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for embedded pjproject (may have to download)" >&5 -$as_echo_n "checking for embedded pjproject (may have to download)... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring" >&5 -$as_echo "configuring" >&6; } - ${GNU_MAKE} --quiet --no-print-directory -C $PJPROJECT_DIR configure - if test $? -ne 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 -$as_echo "failed" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: Unable to configure $PJPROJECT_DIR" >&5 -$as_echo "$as_me: Unable to configure $PJPROJECT_DIR" >&6;} - as_fn_error $? "Run \"${GNU_MAKE} -C $PJPROJECT_DIR NOISY_BUILD=yes configure\" to see error details." "$LINENO" 5 - fi - - PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C $PJPROJECT_DIR echo_cflags) - PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE" - PBX_PJPROJECT=1 - PJPROJECT_BUNDLED=yes - -$as_echo "#define HAVE_PJPROJECT 1" >>confdefs.h - - -$as_echo "#define HAVE_PJPROJECT_BUNDLED 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for embedded pjproject" >&5 -$as_echo_n "checking for embedded pjproject... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - - - PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_INCLUDE="$PJPROJECT_INCLUDE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pjsip_dlg_create_uas_and_inc_lock declared in pjsip.h" >&5 -$as_echo_n "checking for pjsip_dlg_create_uas_and_inc_lock declared in pjsip.h... " >&6; } - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <pjsip.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "pjsip_dlg_create_uas_and_inc_lock" >/dev/null 2>&1; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - PBX_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK=1 - -$as_echo "#define HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK 1" >>confdefs.h - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f conftest* - - - CPPGLAGS="$saved_cpp" - PJSIP_DLG_CREATE_UAS_AND_INC_LOCK_INCLUDE="$PJPROJECT_INCLUDE" - - - PJ_TRANSACTION_GRP_LOCK_INCLUDE="$PJPROJECT_INCLUDE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pjsip_tsx_create_uac2 declared in pjsip.h" >&5 -$as_echo_n "checking for pjsip_tsx_create_uac2 declared in pjsip.h... " >&6; } - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <pjsip.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "pjsip_tsx_create_uac2" >/dev/null 2>&1; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - PBX_PJ_TRANSACTION_GRP_LOCK=1 - -$as_echo "#define HAVE_PJ_TRANSACTION_GRP_LOCK 1" >>confdefs.h - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f conftest* - - - CPPGLAGS="$saved_cpp" - PJ_TRANSACTION_GRP_LOCK_INCLUDE="$PJPROJECT_INCLUDE" - - - PJSIP_REPLACE_MEDIA_STREAM_INCLUDE="$PJPROJECT_INCLUDE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE declared in pjmedia.h" >&5 -$as_echo_n "checking for PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE declared in pjmedia.h... " >&6; } - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <pjmedia.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE" >/dev/null 2>&1; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - PBX_PJSIP_REPLACE_MEDIA_STREAM=1 - -$as_echo "#define HAVE_PJSIP_REPLACE_MEDIA_STREAM 1" >>confdefs.h - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f conftest* - - - CPPGLAGS="$saved_cpp" - PJSIP_REPLACE_MEDIA_STREAM_INCLUDE="$PJPROJECT_INCLUDE" - - - PJSIP_GET_DEST_INFO_INCLUDE="$PJPROJECT_INCLUDE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pjsip_get_dest_info declared in pjsip.h" >&5 -$as_echo_n "checking for pjsip_get_dest_info declared in pjsip.h... " >&6; } - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <pjsip.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "pjsip_get_dest_info" >/dev/null 2>&1; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - PBX_PJSIP_GET_DEST_INFO=1 - -$as_echo "#define HAVE_PJSIP_GET_DEST_INFO 1" >>confdefs.h - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f conftest* - - - CPPGLAGS="$saved_cpp" - PJSIP_GET_DEST_INFO_INCLUDE="$PJPROJECT_INCLUDE" - - - PJ_SSL_CERT_LOAD_FROM_FILES2_INCLUDE="$PJPROJECT_INCLUDE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_ssl_cert_load_from_files2 declared in pjlib.h" >&5 -$as_echo_n "checking for pj_ssl_cert_load_from_files2 declared in pjlib.h... " >&6; } - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <pjlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "pj_ssl_cert_load_from_files2" >/dev/null 2>&1; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - PBX_PJ_SSL_CERT_LOAD_FROM_FILES2=1 - -$as_echo "#define HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2 1" >>confdefs.h - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f conftest* - - - CPPGLAGS="$saved_cpp" - PJ_SSL_CERT_LOAD_FROM_FILES2_INCLUDE="$PJPROJECT_INCLUDE" - - - PJSIP_EXTERNAL_RESOLVER_INCLUDE="$PJPROJECT_INCLUDE" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pjsip_endpt_set_ext_resolver declared in pjsip.h" >&5 -$as_echo_n "checking for pjsip_endpt_set_ext_resolver declared in pjsip.h... " >&6; } - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <pjsip.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "pjsip_endpt_set_ext_resolver" >/dev/null 2>&1; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - PBX_PJSIP_EXTERNAL_RESOLVER=1 - -$as_echo "#define HAVE_PJSIP_EXTERNAL_RESOLVER 1" >>confdefs.h - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -fi -rm -f conftest* - - - CPPGLAGS="$saved_cpp" - PJSIP_EXTERNAL_RESOLVER_INCLUDE="$PJPROJECT_INCLUDE" - - -$as_echo "#define HAVE_PJSIP_TLS_TRANSPORT_PROTO 1" >>confdefs.h - - -$as_echo "#define HAVE_PJSIP_EVSUB_GRP_LOCK 1" >>confdefs.h - - -$as_echo "#define HAVE_PJSIP_INV_SESSION_REF 1" >>confdefs.h - - - else + if test "$PJPROJECT_BUNDLED" = "no" ; then if test "x${PBX_PJPROJECT}" != "x1" -a "${USE_PJPROJECT}" != "no"; then @@ -28920,6 +29022,115 @@ fi +if test "x${PBX_FFTW3}" != "x1" -a "${USE_FFTW3}" != "no"; then + pbxlibdir="" + # if --with-FFTW3=DIR has been specified, use it. + if test "x${FFTW3_DIR}" != "x"; then + if test -d ${FFTW3_DIR}/lib; then + pbxlibdir="-L${FFTW3_DIR}/lib" + else + pbxlibdir="-L${FFTW3_DIR}" + fi + fi + pbxfuncname="fftw_alloc_real" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_FFTW3_FOUND=yes + else + ast_ext_lib_check_save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} " + as_ac_Lib=`$as_echo "ac_cv_lib_fftw3_${pbxfuncname}" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lfftw3" >&5 +$as_echo_n "checking for ${pbxfuncname} in -lfftw3... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfftw3 ${pbxlibdir} -lfftw3 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + AST_FFTW3_FOUND=yes +else + AST_FFTW3_FOUND=no +fi + + CFLAGS="${ast_ext_lib_check_save_CFLAGS}" + fi + + # now check for the header. + if test "${AST_FFTW3_FOUND}" = "yes"; then + FFTW3_LIB="${pbxlibdir} -lfftw3 -lfftw3" + # if --with-FFTW3=DIR has been specified, use it. + if test "x${FFTW3_DIR}" != "x"; then + FFTW3_INCLUDE="-I${FFTW3_DIR}/include" + fi + FFTW3_INCLUDE="${FFTW3_INCLUDE} " + if test "xfftw3.h" = "x" ; then # no header, assume found + FFTW3_HEADER_FOUND="1" + else # check for the header + ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${FFTW3_INCLUDE}" + ac_fn_c_check_header_mongrel "$LINENO" "fftw3.h" "ac_cv_header_fftw3_h" "$ac_includes_default" +if test "x$ac_cv_header_fftw3_h" = xyes; then : + FFTW3_HEADER_FOUND=1 +else + FFTW3_HEADER_FOUND=0 +fi + + + CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}" + fi + if test "x${FFTW3_HEADER_FOUND}" = "x0" ; then + FFTW3_LIB="" + FFTW3_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + FFTW3_LIB="" + fi + PBX_FFTW3=1 + cat >>confdefs.h <<_ACEOF +#define HAVE_FFTW3 1 +_ACEOF + + fi + fi +fi + + +if test "$PBX_FFTW3" = "1"; then + +$as_echo "#define HAVE_FFTW 1" >>confdefs.h + +fi + if test "x${PBX_SPANDSP}" != "x1" -a "${USE_SPANDSP}" != "no"; then if test "xminimum version of SpanDSP" != "x"; then diff --git a/configure.ac b/configure.ac index 17b887266..0f2148b06 100644 --- a/configure.ac +++ b/configure.ac @@ -284,16 +284,27 @@ AC_PATH_PROG([XMLSTARLET], [xmlstarlet], :) AC_PATH_PROG([BASH], [bash], :) AC_PATH_PROG([GIT], [git], :) AC_PATH_PROG([ALEMBIC], [alembic], :) +AC_PATH_PROG([BZIP2], [bzip2], :) +AC_PATH_PROG([TAR], [tar], :) +AC_PATH_PROG([PATCH], [patch], :) +AC_PATH_PROG([SED], [sed], :) +AC_PATH_PROG([NM], [nm], :) + if test "${WGET}" != ":" ; then DOWNLOAD=${WGET} + DOWNLOAD_TO_STDOUT="${WGET} -O-" else if test "${CURL}" != ":" ; then DOWNLOAD="${CURL} -O --progress-bar -w \"%{url_effective}\n\"" + DOWNLOAD_TO_STDOUT="${CURL} -L --progress-bar -w \"%{url_effective}\n\"" else AC_PATH_PROG([FETCH], [fetch], [:]) DOWNLOAD=${FETCH} + DOWNLOAD_TO_STDOUT="${FETCH} -o-" fi fi + AC_SUBST(DOWNLOAD) +AC_SUBST(DOWNLOAD_TO_STDOUT) AC_PATH_PROG([LDCONFIG], [ldconfig], :) AC_PATH_PROG([SHA1SUM], [sha1sum], $ac_aux_dir/build_tools/sha1sum-sh) AC_PATH_PROG([OPENSSL], [openssl], :) @@ -390,6 +401,9 @@ AC_SUBST(NOISY_BUILD) AC_SUBST(AST_DEVMODE) AC_SUBST(AST_DEVMODE_STRICT) +AST_OPTION_ONLY([sounds-cache], [SOUNDS_CACHE_DIR], [cached sound tarfiles], []) +AST_OPTION_ONLY([externals-cache], [EXTERNALS_CACHE_DIR], [cached external module tarfiles], []) + AST_CODE_COVERAGE=no AC_ARG_ENABLE([coverage], [AS_HELP_STRING([--enable-coverage], @@ -404,6 +418,19 @@ AC_SUBST(AST_CODE_COVERAGE) AST_CHECK_RAII() AST_CHECK_STRSEP_ARRAY_BOUNDS() +PJPROJECT_BUNDLED=no +AH_TEMPLATE(m4_bpatsubst([[HAVE_PJPROJECT_BUNDLED]], [(.*)]), [Define to 1 when using the bundled pjproject.]) + +AC_ARG_WITH([pjproject-bundled], + [AS_HELP_STRING([--with-pjproject-bundled], + [Use bundled pjproject libraries])], + [case "${enableval}" in + n|no) PJPROJECT_BUNDLED=no ;; + *) PJPROJECT_BUNDLED=yes ;; + esac]) + +THIRD_PARTY_CONFIGURE() + # AST_EXT_LIB_SETUP is used to tell configure to handle variables for # various packages. # $1 is the prefix for the variables in makeopts and autoconfig.h @@ -472,28 +499,8 @@ AST_EXT_LIB_SETUP([OSPTK], [OSP Toolkit], [osptk]) AST_EXT_LIB_SETUP([OSS], [Open Sound System], [oss]) AST_EXT_LIB_SETUP([PGSQL], [PostgreSQL], [postgres]) +if test "x${PBX_PJPROJECT}" != "x1" ; then AST_EXT_LIB_SETUP([PJPROJECT], [PJPROJECT], [pjproject]) -PJPROJECT_BUNDLED=no -AH_TEMPLATE(m4_bpatsubst([[HAVE_PJPROJECT_BUNDLED]], [(.*)]), [Define to 1 when using the bundled pjproject.]) - -AC_ARG_WITH([pjproject-bundled], - [AS_HELP_STRING([--with-pjproject-bundled], - [Use bundled pjproject libraries])], - [case "${enableval}" in - n|no) PJPROJECT_BUNDLED=no ;; - *) PJPROJECT_BUNDLED=yes ;; - esac]) -AC_SUBST(PJPROJECT_BUNDLED) - -if test "$PJPROJECT_BUNDLED" = "yes" -a "${ac_mandatory_list#*PJPROJECT*}" != "$ac_mandatory_list" ; then - AC_MSG_ERROR(--with-pjproject and --with-pjproject-bundled can't both be specified) -fi - -if test "$PJPROJECT_BUNDLED" = "yes" ; then - ac_mandatory_list="$ac_mandatory_list PJPROJECT" - PJPROJECT_DIR="${ac_top_build_prefix}third-party/pjproject" -fi - AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_DLG_CREATE_UAS_AND_INC_LOCK], [PJSIP Dialog Create UAS with Incremented Lock], [PJPROJECT], [pjsip]) AST_EXT_LIB_SETUP_OPTIONAL([PJ_TRANSACTION_GRP_LOCK], [PJSIP Transaction Group Lock Support], [PJPROJECT], [pjsip]) AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_REPLACE_MEDIA_STREAM], [PJSIP Media Stream Replacement Support], [PJPROJECT], [pjsip]) @@ -503,6 +510,7 @@ AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EXTERNAL_RESOLVER], [PJSIP External Resolver S AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_PROTO], [PJSIP TLS Transport proto field support], [PJPROJECT], [pjsip]) AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EVSUB_GRP_LOCK], [PJSIP EVSUB Group Lock support], [PJPROJECT], [pjsip]) AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_INV_SESSION_REF], [PJSIP INVITE Session Reference Count support], [PJPROJECT], [pjsip]) +fi AST_EXT_LIB_SETUP([POPT], [popt], [popt]) AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio]) @@ -533,11 +541,10 @@ AST_EXT_LIB_SETUP_OPTIONAL([PRI_REVERSE_CHARGE], [ISDN reverse charge], [PRI], [ # ------------------------------------^ AST_EXT_LIB_SETUP([PWLIB], [PWlib], [pwlib]) AST_EXT_LIB_SETUP([RADIUS], [Radius Client], [radius]) +AST_EXT_LIB_SETUP([FFTW3], [LIBFFTW3], [fftw3]) AST_EXT_LIB_SETUP([RESAMPLE], [LIBRESAMPLE], [resample]) AST_EXT_LIB_SETUP([SDL], [Sdl], [sdl]) AST_EXT_LIB_SETUP([SDL_IMAGE], [Sdl Image], [SDL_image]) -AST_OPTION_ONLY([sounds-cache], [SOUNDS_CACHE_DIR], [cached sound tarfiles], []) -AST_OPTION_ONLY([externals-cache], [EXTERNALS_CACHE_DIR], [cached external module tarfiles], []) AST_EXT_LIB_SETUP([SPANDSP], [SPANDSP], [spandsp]) AST_EXT_LIB_SETUP([SS7], [ISDN SS7], [ss7]) AST_EXT_LIB_SETUP([SPEEX], [Speex], [speex]) @@ -2198,9 +2205,7 @@ if test "${PG_CONFIG}" != No; then fi if test "$USE_PJPROJECT" != "no" ; then - if test "$PJPROJECT_BUNDLED" = "yes" ; then - PJPROJECT_CONFIGURE([$PJPROJECT_DIR]) - else + if test "$PJPROJECT_BUNDLED" = "no" ; then AST_PKG_CONFIG_CHECK([PJPROJECT], [libpjproject]) AST_EXT_LIB_CHECK([PJSIP_DLG_CREATE_UAS_AND_INC_LOCK], [pjsip], [pjsip_dlg_create_uas_and_inc_lock], [pjsip.h], [$PJPROJECT_LIBS], [$PJPROJECT_CFLAGS]) @@ -2267,6 +2272,10 @@ AST_EXT_LIB_CHECK([PRI_REVERSE_CHARGE], [pri], [pri_sr_set_reversecharge], [libp # ------------------------------------^ AST_EXT_LIB_CHECK([RESAMPLE], [resample], [resample_open], [libresample.h], [-lm]) +AST_EXT_LIB_CHECK([FFTW3], [fftw3], [fftw_alloc_real], [fftw3.h], [-lfftw3]) +if test "$PBX_FFTW3" = "1"; then + AC_DEFINE([HAVE_FFTW], 1, [Define 1 if your system has fftw.]) +fi AST_C_COMPILE_CHECK([SPANDSP], [ #if SPANDSP_RELEASE_DATE < 20080516 diff --git a/contrib/ast-db-manage/README.md b/contrib/ast-db-manage/README.md index 3444dd5cd..7add3ee66 100644 --- a/contrib/ast-db-manage/README.md +++ b/contrib/ast-db-manage/README.md @@ -9,6 +9,7 @@ This is implemented as a set of repositories that contain database schema migrations, using [Alembic](http://alembic.readthedocs.org). The existing repositories include: + * `cdr` - Table used for Asterisk to store CDR records * `config` - Tables used for Asterisk realtime configuration * `voicemail` - Tables used for `ODBC_STOARGE` of voicemail messages diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index e16b66861..706798ced 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -239,6 +239,12 @@ /* Define to 1 if you have the `ffsll' function. */ #undef HAVE_FFSLL +/* Define 1 if your system has fftw. */ +#undef HAVE_FFTW + +/* Define to 1 if you have the LIBFFTW3 library. */ +#undef HAVE_FFTW3 + /* Define to 1 if you have the `floor' function. */ #undef HAVE_FLOOR @@ -586,19 +592,22 @@ /* Define if your system has PJPROJECT_BUNDLED */ #undef HAVE_PJPROJECT_BUNDLED -/* Define if your system has pjsip_dlg_create_uas_and_inc_lock declared. */ +/* Define to 1 if PJPROJECT has the PJSIP Dialog Create UAS with Incremented + Lock feature. */ #undef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK -/* Define if your system has PJSIP_EVSUB_GRP_LOCK */ +/* Define to 1 if PJPROJECT has the PJSIP EVSUB Group Lock support feature. */ #undef HAVE_PJSIP_EVSUB_GRP_LOCK -/* Define if your system has pjsip_endpt_set_ext_resolver declared. */ +/* Define to 1 if PJPROJECT has the PJSIP External Resolver Support feature. + */ #undef HAVE_PJSIP_EXTERNAL_RESOLVER -/* Define if your system has pjsip_get_dest_info declared. */ +/* Define to 1 if PJPROJECT has the pjsip_get_dest_info support feature. */ #undef HAVE_PJSIP_GET_DEST_INFO -/* Define if your system has PJSIP_INV_SESSION_REF */ +/* Define to 1 if PJPROJECT has the PJSIP INVITE Session Reference Count + support feature. */ #undef HAVE_PJSIP_INV_SESSION_REF /* Define if your system has the PJSIP_REPLACE_MEDIA_STREAM headers. */ @@ -607,10 +616,12 @@ /* Define if your system has the PJSIP_TLS_TRANSPORT_PROTO headers. */ #undef HAVE_PJSIP_TLS_TRANSPORT_PROTO -/* Define if your system has pj_ssl_cert_load_from_files2 declared. */ +/* Define to 1 if PJPROJECT has the pj_ssl_cert_load_from_files2 support + feature. */ #undef HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2 -/* Define if your system has pjsip_tsx_create_uac2 declared. */ +/* Define to 1 if PJPROJECT has the PJSIP Transaction Group Lock Support + feature. */ #undef HAVE_PJ_TRANSACTION_GRP_LOCK /* Define to 1 if your system defines IP_PKTINFO. */ diff --git a/include/asterisk/calendar.h b/include/asterisk/calendar.h index da4af01ef..e9dcd8809 100644 --- a/include/asterisk/calendar.h +++ b/include/asterisk/calendar.h @@ -129,6 +129,7 @@ struct ast_calendar { int autoreminder; /*!< If set, override any calendar_tech specific notification times and use this time (in mins) */ int notify_waittime; /*!< Maxiumum time to allow for a notification attempt */ int refresh; /*!< When to refresh the calendar events */ + int fetch_again_at_reload; /*!< To reload the calendar content when the module is reloaded */ int timeframe; /*!< Span (in mins) of calendar data to pull with each request */ pthread_t thread; /*!< The thread that the calendar is loaded/updated in */ ast_cond_t unload; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 3293dd77b..df752c902 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2017,6 +2017,16 @@ int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_ca int ast_set_write_format(struct ast_channel *chan, struct ast_format *format); /*! + * \brief Sets write format for a channel. + * All internal data will than be handled in an interleaved format. (needed by binaural opus) + * + * \param chan channel to change + * \param format format to set for writing + * \return Returns 0 on success, -1 on failure + */ +int ast_set_write_format_interleaved_stereo(struct ast_channel *chan, struct ast_format *format); + +/*! * \brief Sends text to a channel * * \param chan channel to act upon diff --git a/include/asterisk/json.h b/include/asterisk/json.h index 28ebfbd51..cfd9a2997 100644 --- a/include/asterisk/json.h +++ b/include/asterisk/json.h @@ -217,6 +217,41 @@ const char *ast_json_typename(enum ast_json_type type); /*!@{*/ /*! + * \brief Check the string of the given length for UTF-8 format. + * \since 13.12.0 + * + * \param str String to check. + * \param len Length of string to check. + * + * \retval 0 if not UTF-8 encoded or str is NULL. + * \retval 1 if UTF-8 encoded. + */ +int ast_json_utf8_check_len(const char *str, size_t len); + +/*! + * \brief Check the nul terminated string for UTF-8 format. + * \since 13.12.0 + * + * \param str String to check. + * + * \retval 0 if not UTF-8 encoded or str is NULL. + * \retval 1 if UTF-8 encoded. + */ +int ast_json_utf8_check(const char *str); + +/*! + * \brief Check str for UTF-8 and replace with an empty string if fails the check. + * + * \note The convenience macro is normally used with ast_json_pack() + * or a function wrapper that calls ast_json_vpack(). + */ +#define AST_JSON_UTF8_VALIDATE(str) (ast_json_utf8_check(str) ? (str) : "") + +/*!@}*/ + +/*!@{*/ + +/*! * \brief Get the JSON true value. * \since 12.0.0 * diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h index b8cd21971..8188eb8eb 100644 --- a/include/asterisk/translate.h +++ b/include/asterisk/translate.h @@ -231,6 +231,7 @@ struct ast_trans_pvt { * explicit_dst contains an attribute which describes whether both parties * want to do forward-error correction (FEC). */ struct ast_format *explicit_dst; + int interleaved_stereo; /*!< indicates if samples are in interleaved order, for stereo lin */ }; /*! \brief generic frameout function */ diff --git a/include/asterisk/vector.h b/include/asterisk/vector.h index b4a8a2c11..c74f0a89b 100644 --- a/include/asterisk/vector.h +++ b/include/asterisk/vector.h @@ -367,11 +367,13 @@ int count = 0; \ size_t idx; \ typeof(value) __value = (value); \ - for (idx = 0; idx < (vec)->current; ++idx) { \ + for (idx = 0; idx < (vec)->current; ) { \ if (cmp((vec)->elems[idx], __value)) { \ cleanup((vec)->elems[idx]); \ AST_VECTOR_REMOVE_UNORDERED((vec), idx); \ ++count; \ + } else { \ + ++idx; \ } \ } \ count; \ @@ -417,14 +419,16 @@ int count = 0; \ size_t idx; \ typeof(value) __value = (value); \ - for (idx = 0; idx < (vec)->current; ++idx) { \ + for (idx = 0; idx < (vec)->current; ) { \ if (cmp((vec)->elems[idx], __value)) { \ cleanup((vec)->elems[idx]); \ - AST_VECTOR_REMOVE_ORDERED((vec), idx); \ + AST_VECTOR_REMOVE_ORDERED((vec), idx); \ ++count; \ + } else { \ + ++idx; \ } \ } \ - oount; \ + count; \ }) /*! @@ -445,7 +449,7 @@ for (idx = 0; idx < (vec)->current; ++idx) { \ if (cmp((vec)->elems[idx], __value)) { \ cleanup((vec)->elems[idx]); \ - AST_VECTOR_REMOVE_ORDERED((vec), idx); \ + AST_VECTOR_REMOVE_ORDERED((vec), idx); \ res = 0; \ break; \ } \ diff --git a/main/aoc.c b/main/aoc.c index cd9c461c1..8d4332901 100644 --- a/main/aoc.c +++ b/main/aoc.c @@ -1656,8 +1656,10 @@ static struct ast_json *units_to_json(const struct ast_aoc_decoded *decoded) static struct ast_json *currency_to_json(const char *name, int cost, enum ast_aoc_currency_multiplier mult) { - return ast_json_pack("{s:s, s:i, s:s}", "Name", name, - "Cost", cost, "Multiplier", aoc_multiplier_str(mult)); + return ast_json_pack("{s:s, s:i, s:s}", + "Name", AST_JSON_UTF8_VALIDATE(name), + "Cost", cost, + "Multiplier", aoc_multiplier_str(mult)); } static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded) @@ -1667,8 +1669,8 @@ static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded) if (decoded->charge_type != AST_AOC_CHARGE_CURRENCY && decoded->charge_type != AST_AOC_CHARGE_UNIT) { - return ast_json_pack("{s:s}", "Type", - aoc_charge_type_str(decoded->charge_type)); + return ast_json_pack("{s:s}", + "Type", aoc_charge_type_str(decoded->charge_type)); } if (decoded->charge_type == AST_AOC_CHARGE_CURRENCY) { @@ -1680,8 +1682,7 @@ static struct ast_json *charge_to_json(const struct ast_aoc_decoded *decoded) obj = units_to_json(decoded); } - return ast_json_pack( - "{s:s, s:s, s:s, s:o}", + return ast_json_pack("{s:s, s:s, s:s, s:o}", "Type", aoc_charge_type_str(decoded->charge_type), "BillingID", aoc_billingid_str(decoded->billing_id), "TotalType", aoc_type_of_totaling_str(decoded->total_type), @@ -1692,13 +1693,11 @@ static struct ast_json *association_to_json(const struct ast_aoc_decoded *decode { switch (decoded->charging_association.charging_type) { case AST_AOC_CHARGING_ASSOCIATION_NUMBER: - return ast_json_pack( - "{s:s, s:i}", - "Number", decoded->charging_association.charge.number.number, + return ast_json_pack("{s:s, s:i}", + "Number", AST_JSON_UTF8_VALIDATE(decoded->charging_association.charge.number.number), "Plan", decoded->charging_association.charge.number.plan); case AST_AOC_CHARGING_ASSOCIATION_ID: - return ast_json_pack( - "{s:i}", "ID", decoded->charging_association.charge.id); + return ast_json_pack("{s:i}", "ID", decoded->charging_association.charge.id); case AST_AOC_CHARGING_ASSOCIATION_NA: default: return ast_json_null(); @@ -1740,22 +1739,22 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded) decoded->aoc_s_entries[i].rate.duration.amount, decoded->aoc_s_entries[i].rate.duration.multiplier); - time = ast_json_pack( - "{s:i, s:s}", + time = ast_json_pack("{s:i, s:i}", "Length", decoded->aoc_s_entries[i].rate.duration.time, "Scale", decoded->aoc_s_entries[i].rate.duration.time_scale); if (decoded->aoc_s_entries[i].rate.duration.granularity_time) { - granularity = ast_json_pack( - "{s:i, s:s}", + granularity = ast_json_pack("{s:i, s:i}", "Length", decoded->aoc_s_entries[i].rate.duration.granularity_time, "Scale", decoded->aoc_s_entries[i].rate.duration.granularity_time_scale); } - type = ast_json_pack("{s:o, s:s, s:o, s:o}", "Currency", ast_json_ref(currency), "ChargingType", - decoded->aoc_s_entries[i].rate.duration.charging_type ? - "StepFunction" : "ContinuousCharging", "Time", ast_json_ref(time), - "Granularity", granularity ? ast_json_ref(granularity) : ast_json_ref(ast_json_null())); + type = ast_json_pack("{s:o, s:s, s:o, s:o}", + "Currency", ast_json_ref(currency), + "ChargingType", decoded->aoc_s_entries[i].rate.duration.charging_type + ? "StepFunction" : "ContinuousCharging", + "Time", ast_json_ref(time), + "Granularity", granularity ? ast_json_ref(granularity) : ast_json_null()); break; } @@ -1773,21 +1772,22 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded) decoded->aoc_s_entries[i].rate.volume.amount, decoded->aoc_s_entries[i].rate.volume.multiplier); - type = ast_json_pack( - "{s:s, s:o}", "Unit", aoc_volume_unit_str( + type = ast_json_pack("{s:s, s:o}", + "Unit", aoc_volume_unit_str( decoded->aoc_s_entries[i].rate.volume.volume_unit), "Currency", ast_json_ref(currency)); break; case AST_AOC_RATE_TYPE_SPECIAL_CODE: - type = ast_json_pack("{s:i}", "SpecialCode", - decoded->aoc_s_entries[i].rate.special_code); + type = ast_json_pack("{s:i}", + "SpecialCode", decoded->aoc_s_entries[i].rate.special_code); break; default: break; } - rate = ast_json_pack("{s:s, s:o}", "Chargeable", charge_item, - aoc_rate_type_str(decoded->aoc_s_entries[i].rate_type), ast_json_ref(type)); + rate = ast_json_pack("{s:s, s:o}", + "Chargeable", charge_item, + aoc_rate_type_str(decoded->aoc_s_entries[i].rate_type), ast_json_ref(type)); if (ast_json_array_append(rates, rate)) { break; } diff --git a/main/cdr.c b/main/cdr.c index e2f9b764c..baa17b967 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -698,6 +698,7 @@ struct cdr_object { ); struct cdr_object *next; /*!< The next CDR object in the chain */ struct cdr_object *last; /*!< The last CDR object in the chain */ + int is_root; /*!< True if this is the first CDR in the chain */ }; /*! @@ -853,7 +854,22 @@ static void cdr_object_dtor(void *obj) } ast_string_field_free_memory(cdr); - ao2_cleanup(cdr->next); + /* CDR destruction used to work by calling ao2_cleanup(next) and + * allowing the chain to destroy itself neatly. Unfortunately, for + * really long chains, this can result in a stack overflow. So now + * when the root CDR is destroyed, it is responsible for unreffing + * all CDRs in the chain + */ + if (cdr->is_root) { + struct cdr_object *curr = cdr->next; + struct cdr_object *next; + + while (curr) { + next = curr->next; + ao2_cleanup(curr); + curr = next; + } + } } /*! @@ -2100,6 +2116,7 @@ static void handle_channel_cache_message(void *data, struct stasis_subscription if (!cdr) { return; } + cdr->is_root = 1; ao2_link(active_cdrs_by_channel, cdr); } diff --git a/main/cel.c b/main/cel.c index ad75c0186..aafeea432 100644 --- a/main/cel.c +++ b/main/cel.c @@ -1237,10 +1237,10 @@ static void cel_parking_cb( if (parked_payload->retriever) { extra = ast_json_pack("{s: s, s: s}", - "reason", reason, + "reason", reason ?: "", "retriever", parked_payload->retriever->name); } else { - extra = ast_json_pack("{s: s}", "reason", reason); + extra = ast_json_pack("{s: s}", "reason", reason ?: ""); } if (extra) { diff --git a/main/channel.c b/main/channel.c index 94505ad0e..6804496f4 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3914,6 +3914,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) struct ast_frame *readq_tail = AST_LIST_LAST(ast_channel_readq(chan)); struct ast_control_read_action_payload *read_action_payload; struct ast_party_connected_line connected; + int hooked = 0; /* if the channel driver returned more than one frame, stuff the excess into the readq for the next ast_read call @@ -4191,15 +4192,22 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) break; } } - /* Send frame to audiohooks if present */ - if (ast_channel_audiohooks(chan)) { + /* + * Send frame to audiohooks if present, if frametype is linear, to preserve + * functional compatibility with previous behavior. If not linear, hold off + * until transcoding is done where we are more likely to have a linear frame + */ + if (ast_channel_audiohooks(chan) && ast_format_cache_is_slinear(f->subclass.format)) { + /* Place hooked after declaration */ struct ast_frame *old_frame = f; + hooked = 1; f = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_READ, f); if (old_frame != f) { ast_frfree(old_frame); } } + if (ast_channel_monitor(chan) && ast_channel_monitor(chan)->read_stream) { /* XXX what does this do ? */ #ifndef MONITOR_CONSTANT_DELAY @@ -4242,6 +4250,16 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) } } + /* Second chance at hooking a linear frame, also the last chance */ + if (ast_channel_audiohooks(chan) && !hooked) { + struct ast_frame *old_frame = f; + + f = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_READ, f); + if (old_frame != f) { + ast_frfree(old_frame); + } + } + /* * It is possible for the translation process on the channel to have * produced multiple frames from the single input frame we passed it; if @@ -5032,6 +5050,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) int res = -1; struct ast_frame *f = NULL; int count = 0; + int hooked = 0; /*Deadlock avoidance*/ while(ast_channel_trylock(chan)) { @@ -5149,6 +5168,22 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) apply_plc(chan, fr); } + /* + * Send frame to audiohooks if present, if frametype is linear (else, later as per + * previous behavior) + */ + if (ast_channel_audiohooks(chan)) { + if (ast_format_cache_is_slinear(fr->subclass.format)) { + struct ast_frame *old_frame; + hooked = 1; + old_frame = fr; + fr = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_WRITE, fr); + if (old_frame != fr) { + ast_frfree(old_frame); + } + } + } + /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */ if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) == AST_FORMAT_CMP_EQUAL) { f = fr; @@ -5186,7 +5221,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) break; } - if (ast_channel_audiohooks(chan)) { + if (ast_channel_audiohooks(chan) && !hooked) { struct ast_frame *prev = NULL, *new_frame, *cur, *dup; int freeoldlist = 0; @@ -5407,7 +5442,7 @@ static const struct set_format_access set_format_access_write = { .setoption = AST_OPTION_FORMAT_WRITE, }; -static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, const int direction) +static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, const int direction, int interleaved_stereo) { struct ast_trans_pvt *trans_pvt; struct ast_format_cap *cap_native; @@ -5509,16 +5544,20 @@ static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, } /* Now we have a good choice for both. */ + trans_pvt = access->get_trans(chan); if ((ast_format_cmp(rawformat, best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) && (ast_format_cmp(format, best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) && ((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || access->get_trans(chan))) { - /* the channel is already in these formats, so nothing to do */ - ast_channel_unlock(chan); - return 0; + /* the channel is already in these formats, so nothing to do, unless the interleaved format is not set correctly */ + if (trans_pvt != NULL) { + if (trans_pvt->interleaved_stereo == interleaved_stereo) { + ast_channel_unlock(chan); + return 0; + } + } } /* Free any translation we have right now */ - trans_pvt = access->get_trans(chan); if (trans_pvt) { ast_translator_free_path(trans_pvt); access->set_trans(chan, NULL); @@ -5536,9 +5575,11 @@ static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, if (!direction) { /* reading */ trans_pvt = ast_translator_build_path(best_set_fmt, best_native_fmt); + trans_pvt->interleaved_stereo = 0; } else { /* writing */ trans_pvt = ast_translator_build_path(best_native_fmt, best_set_fmt); + trans_pvt->interleaved_stereo = interleaved_stereo; } access->set_trans(chan, trans_pvt); res = trans_pvt ? 0 : -1; @@ -5578,7 +5619,7 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format) } ast_format_cap_append(cap, format, 0); - res = set_format(chan, cap, 0); + res = set_format(chan, cap, 0, 0); ao2_cleanup(cap); return res; @@ -5586,7 +5627,25 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format) int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap) { - return set_format(chan, cap, 0); + return set_format(chan, cap, 0, 0); +} + +int ast_set_write_format_interleaved_stereo(struct ast_channel *chan, struct ast_format *format) +{ + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + int res; + + ast_assert(format != NULL); + + if (!cap) { + return -1; + } + ast_format_cap_append(cap, format, 0); + + res = set_format(chan, cap, 1, 1); + + ao2_cleanup(cap); + return res; } int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) @@ -5601,7 +5660,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) } ast_format_cap_append(cap, format, 0); - res = set_format(chan, cap, 1); + res = set_format(chan, cap, 1, 0); ao2_cleanup(cap); return res; @@ -5609,7 +5668,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap) { - return set_format(chan, cap, 1); + return set_format(chan, cap, 1, 0); } const char *ast_channel_reason2str(int reason) diff --git a/main/cli.c b/main/cli.c index 8af20b61b..3ba743d75 100644 --- a/main/cli.c +++ b/main/cli.c @@ -449,19 +449,11 @@ static char *handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args case CLI_INIT: e->command = "core set debug"; e->usage = -#if !defined(LOW_MEMORY) "Usage: core set debug [atleast] <level> [module]\n" -#else - "Usage: core set debug [atleast] <level>\n" -#endif " core set debug off\n" "\n" -#if !defined(LOW_MEMORY) " Sets level of debug messages to be displayed or\n" " sets a module name to display debug messages from.\n" -#else - " Sets level of debug messages to be displayed.\n" -#endif " 0 or off means no messages should be displayed.\n" " Equivalent to -d[d[...]] on startup\n"; return NULL; @@ -489,13 +481,9 @@ static char *handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) { return ast_strdup("atleast"); } -#if !defined(LOW_MEMORY) } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel")) || (a->pos == 5 && atleast)) { - const char *pos = S_OR(a->argv[a->pos], ""); - - return ast_complete_source_filename(pos, a->n); -#endif + return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0); } return NULL; } diff --git a/main/json.c b/main/json.c index 12d5fc865..ca74f85dc 100644 --- a/main/json.c +++ b/main/json.c @@ -269,6 +269,127 @@ const char *ast_json_typename(enum ast_json_type type) return "?"; } +/* Ported from libjansson utf.c:utf8_check_first() */ +static size_t json_utf8_check_first(char byte) +{ + unsigned char ch = (unsigned char) byte; + + if (ch < 0x80) { + return 1; + } + + if (0x80 <= ch && ch <= 0xBF) { + /* second, third or fourth byte of a multi-byte + sequence, i.e. a "continuation byte" */ + return 0; + } else if (ch == 0xC0 || ch == 0xC1) { + /* overlong encoding of an ASCII byte */ + return 0; + } else if (0xC2 <= ch && ch <= 0xDF) { + /* 2-byte sequence */ + return 2; + } else if (0xE0 <= ch && ch <= 0xEF) { + /* 3-byte sequence */ + return 3; + } else if (0xF0 <= ch && ch <= 0xF4) { + /* 4-byte sequence */ + return 4; + } else { /* ch >= 0xF5 */ + /* Restricted (start of 4-, 5- or 6-byte sequence) or invalid + UTF-8 */ + return 0; + } +} + +/* Ported from libjansson utf.c:utf8_check_full() */ +static size_t json_utf8_check_full(const char *str, size_t len) +{ + size_t pos; + int32_t value; + unsigned char ch = (unsigned char) str[0]; + + if (len == 2) { + value = ch & 0x1F; + } else if (len == 3) { + value = ch & 0xF; + } else if (len == 4) { + value = ch & 0x7; + } else { + return 0; + } + + for (pos = 1; pos < len; ++pos) { + ch = (unsigned char) str[pos]; + if (ch < 0x80 || ch > 0xBF) { + /* not a continuation byte */ + return 0; + } + + value = (value << 6) + (ch & 0x3F); + } + + if (value > 0x10FFFF) { + /* not in Unicode range */ + return 0; + } else if (0xD800 <= value && value <= 0xDFFF) { + /* invalid code point (UTF-16 surrogate halves) */ + return 0; + } else if ((len == 2 && value < 0x80) + || (len == 3 && value < 0x800) + || (len == 4 && value < 0x10000)) { + /* overlong encoding */ + return 0; + } + + return 1; +} + +int ast_json_utf8_check_len(const char *str, size_t len) +{ + size_t pos; + size_t count; + int res = 1; + + if (!str) { + return 0; + } + + /* + * Since the json library does not make the check function + * public we recreate/copy the function in our interface + * module. + * + * Loop ported from libjansson utf.c:utf8_check_string() + */ + for (pos = 0; pos < len; pos += count) { + count = json_utf8_check_first(str[pos]); + if (count == 0) { + res = 0; + break; + } else if (count > 1) { + if (count > len - pos) { + /* UTF-8 needs more than we have left in the string. */ + res = 0; + break; + } + + if (!json_utf8_check_full(&str[pos], count)) { + res = 0; + break; + } + } + } + + if (!res) { + ast_debug(1, "String '%.*s' is not UTF-8 for json conversion\n", (int) len, str); + } + return res; +} + +int ast_json_utf8_check(const char *str) +{ + return str ? ast_json_utf8_check_len(str, strlen(str)) : 0; +} struct ast_json *ast_json_true(void) { @@ -721,16 +842,16 @@ struct ast_json *ast_json_deep_copy(const struct ast_json *value) struct ast_json *ast_json_name_number(const char *name, const char *number) { return ast_json_pack("{s: s, s: s}", - "name", name, - "number", number); + "name", AST_JSON_UTF8_VALIDATE(name), + "number", AST_JSON_UTF8_VALIDATE(number)); } struct ast_json *ast_json_dialplan_cep(const char *context, const char *exten, int priority) { return ast_json_pack("{s: o, s: o, s: o}", - "context", context ? ast_json_string_create(context) : ast_json_null(), - "exten", exten ? ast_json_string_create(exten) : ast_json_null(), - "priority", priority != -1 ? ast_json_integer_create(priority) : ast_json_null()); + "context", context ? ast_json_string_create(context) : ast_json_null(), + "exten", exten ? ast_json_string_create(exten) : ast_json_null(), + "priority", priority != -1 ? ast_json_integer_create(priority) : ast_json_null()); } struct ast_json *ast_json_timeval(const struct timeval tv, const char *zone) @@ -821,7 +942,7 @@ static struct ast_json *json_party_number(struct ast_party_number *number) return NULL; } return ast_json_pack("{s: s, s: i, s: i, s: s}", - "number", number->str, + "number", AST_JSON_UTF8_VALIDATE(number->str), "plan", number->plan, "presentation", number->presentation, "presentation_txt", ast_describe_caller_presentation(number->presentation)); @@ -833,7 +954,7 @@ static struct ast_json *json_party_name(struct ast_party_name *name) return NULL; } return ast_json_pack("{s: s, s: s, s: i, s: s}", - "name", name->str, + "name", AST_JSON_UTF8_VALIDATE(name->str), "character_set", ast_party_name_charset_describe(name->char_set), "presentation", name->presentation, "presentation_txt", ast_describe_caller_presentation(name->presentation)); @@ -845,7 +966,7 @@ static struct ast_json *json_party_subaddress(struct ast_party_subaddress *subad return NULL; } return ast_json_pack("{s: s, s: i, s: b}", - "subaddress", subaddress->str, + "subaddress", AST_JSON_UTF8_VALIDATE(subaddress->str), "type", subaddress->type, "odd", subaddress->odd_even_indicator); } @@ -865,17 +986,20 @@ struct ast_json *ast_json_party_id(struct ast_party_id *party) } /* Party number */ - if (party->number.valid && ast_json_object_set(json_party_id, "number", json_party_number(&party->number))) { + if (party->number.valid + && ast_json_object_set(json_party_id, "number", json_party_number(&party->number))) { return NULL; } /* Party name */ - if (party->name.valid && ast_json_object_set(json_party_id, "name", json_party_name(&party->name))) { + if (party->name.valid + && ast_json_object_set(json_party_id, "name", json_party_name(&party->name))) { return NULL; } /* Party subaddress */ - if (party->subaddress.valid && ast_json_object_set(json_party_id, "subaddress", json_party_subaddress(&party->subaddress))) { + if (party->subaddress.valid + && ast_json_object_set(json_party_id, "subaddress", json_party_subaddress(&party->subaddress))) { return NULL; } diff --git a/main/logger.c b/main/logger.c index d4cd25122..7d0d2de1e 100644 --- a/main/logger.c +++ b/main/logger.c @@ -1867,6 +1867,10 @@ static void __attribute__((format(printf, 7, 0))) ast_log_full(int level, int su int res = 0; char datestring[256]; + if (level == __LOG_VERBOSE && ast_opt_remote && ast_opt_exec) { + return; + } + if (!(buf = ast_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE))) return; diff --git a/makeopts.in b/makeopts.in index b2b394b5f..a145b02e6 100644 --- a/makeopts.in +++ b/makeopts.in @@ -27,6 +27,7 @@ STRIP=@STRIP@ WGET=@WGET@ FETCH=@FETCH@ DOWNLOAD=@DOWNLOAD@ +DOWNLOAD_TO_STDOUT=@DOWNLOAD_TO_STDOUT@ SOUNDS_CACHE_DIR=@SOUNDS_CACHE_DIR@ EXTERNALS_CACHE_DIR=@EXTERNALS_CACHE_DIR@ RUBBER=@RUBBER@ @@ -41,6 +42,10 @@ OPENSSL=@OPENSSL@ LDCONFIG=@LDCONFIG@ GIT=@GIT@ ALEMBIC=@ALEMBIC@ +TAR=@TAR@ +PATCH=@PATCH@ +SED=@SED@ +NM=@NM@ BUILD_PLATFORM=@BUILD_PLATFORM@ BUILD_CPU=@BUILD_CPU@ @@ -254,6 +259,9 @@ PYTHONDEV_LIB=@PYTHONDEV_LIB@ RESAMPLE_INCLUDE=@RESAMPLE_INCLUDE@ RESAMPLE_LIB=@RESAMPLE_LIB@ +FFTW3_INCLUDE=@FFTW3_INCLUDE@ +FFTW3_LIB=@FFTW3_LIB@ + RT_LIB=@RT_LIB@ SS7_INCLUDE=@SS7_INCLUDE@ diff --git a/menuselect/aclocal.m4 b/menuselect/aclocal.m4 index 8b547156d..e67774c06 100644 --- a/menuselect/aclocal.m4 +++ b/menuselect/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.14.1 -*- Autoconf -*- +# generated automatically by aclocal 1.15 -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -12,8 +12,285 @@ # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>. +dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com> +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + m4_include([../autoconf/ast_check_gnu_make.m4]) m4_include([../autoconf/ast_ext_lib.m4]) m4_include([../autoconf/ast_ext_tool_check.m4]) m4_include([../autoconf/ast_gcc_attribute.m4]) +m4_include([../autoconf/ast_pkgconfig.m4]) m4_include([../autoconf/ast_prog_sed.m4]) diff --git a/menuselect/configure b/menuselect/configure index 648091e5f..4235ea0a4 100755 --- a/menuselect/configure +++ b/menuselect/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 418850 . +# From configure.ac Revision. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # @@ -628,7 +628,11 @@ LIBOBJS GTK2_LIB GTK2_INCLUDE PBX_GTK2 -PKGCONFIG +GTK2_LIBS +GTK2_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG CONFIG_LIBXML2 SED PBX_LIBXML2 @@ -725,7 +729,12 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP' +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +GTK2_CFLAGS +GTK2_LIBS' # Initialize some variables set by options. @@ -1356,6 +1365,13 @@ Some influential environment variables: CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + GTK2_CFLAGS C compiler flags for GTK2, overriding pkg-config + GTK2_LIBS linker flags for GTK2, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -4752,26 +4768,35 @@ if test "${PBX_LIBXML2}" != 1; then as_fn_error $? "Could not find required 'Libxml2' development package" "$LINENO" 5 fi -PBX_GTK2=0 -if test -n "$ac_tool_prefix"; then + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_PKGCONFIG+:} false; then : +if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$PKGCONFIG"; then - ac_cv_prog_PKGCONFIG="$PKGCONFIG" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_PKGCONFIG="${ac_tool_prefix}pkg-config" + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -4779,12 +4804,13 @@ done done IFS=$as_save_IFS + ;; +esac fi -fi -PKGCONFIG=$ac_cv_prog_PKGCONFIG -if test -n "$PKGCONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 -$as_echo "$PKGCONFIG" >&6; } +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -4792,26 +4818,28 @@ fi fi -if test -z "$ac_cv_prog_PKGCONFIG"; then - ac_ct_PKGCONFIG=$PKGCONFIG +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_PKGCONFIG+:} false; then : +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_PKGCONFIG"; then - ac_cv_prog_ac_ct_PKGCONFIG="$ac_ct_PKGCONFIG" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_PKGCONFIG="pkg-config" + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -4819,19 +4847,20 @@ done done IFS=$as_save_IFS + ;; +esac fi -fi -ac_ct_PKGCONFIG=$ac_cv_prog_ac_ct_PKGCONFIG -if test -n "$ac_ct_PKGCONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PKGCONFIG" >&5 -$as_echo "$ac_ct_PKGCONFIG" >&6; } +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - if test "x$ac_ct_PKGCONFIG" = x; then - PKGCONFIG="No" + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) @@ -4839,20 +4868,114 @@ yes:) $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac - PKGCONFIG=$ac_ct_PKGCONFIG + PKG_CONFIG=$ac_pt_PKG_CONFIG fi else - PKGCONFIG="$ac_cv_prog_PKGCONFIG" + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi fi -if test ! "x${PKGCONFIG}" = xNo; then - GTK2_INCLUDE=$(${PKGCONFIG} gtk+-2.0 --cflags 2>/dev/null) - GTK2_LIB=$(${PKGCONFIG} gtk+-2.0 --libs) - PBX_GTK2=1 + if test "x${PBX_GTK2}" != "x1" -a "${USE_GTK2}" != "no"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK2" >&5 +$as_echo_n "checking for GTK2... " >&6; } + +if test -n "$GTK2_CFLAGS"; then + pkg_cv_GTK2_CFLAGS="$GTK2_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK2_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTK2_LIBS"; then + pkg_cv_GTK2_LIBS="$GTK2_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK2_LIBS=`$PKG_CONFIG --libs "gtk+-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTK2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-2.0" 2>&1` + else + GTK2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTK2_PKG_ERRORS" >&5 + + + PBX_GTK2=0 + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + PBX_GTK2=0 + + +else + GTK2_CFLAGS=$pkg_cv_GTK2_CFLAGS + GTK2_LIBS=$pkg_cv_GTK2_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + PBX_GTK2=1 + GTK2_INCLUDE="$GTK2_CFLAGS" + GTK2_LIB="$GTK2_LIBS" $as_echo "#define HAVE_GTK2 1" >>confdefs.h + fi + fi + diff --git a/menuselect/configure.ac b/menuselect/configure.ac index 5989f5cd3..29c43cb50 100644 --- a/menuselect/configure.ac +++ b/menuselect/configure.ac @@ -134,14 +134,7 @@ if test "${PBX_LIBXML2}" != 1; then AC_MSG_ERROR([Could not find required 'Libxml2' development package]) fi -PBX_GTK2=0 -AC_CHECK_TOOL(PKGCONFIG, pkg-config, No) -if test ! "x${PKGCONFIG}" = xNo; then - GTK2_INCLUDE=$(${PKGCONFIG} gtk+-2.0 --cflags 2>/dev/null) - GTK2_LIB=$(${PKGCONFIG} gtk+-2.0 --libs) - PBX_GTK2=1 - AC_DEFINE([HAVE_GTK2], 1, [Define if your system has the GTK2 libraries.]) -fi +AST_PKG_CONFIG_CHECK([GTK2], [gtk+-2.0]) AC_SUBST(PBX_GTK2) AC_SUBST(GTK2_INCLUDE) AC_SUBST(GTK2_LIB) diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c index 8f05db035..633a94c1b 100644 --- a/res/ari/ari_model_validators.c +++ b/res/ari/ari_model_validators.c @@ -1941,6 +1941,15 @@ int ast_ari_validate_application_replaced(struct ast_json *json) int has_application = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ApplicationReplaced field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2009,6 +2018,15 @@ int ast_ari_validate_bridge_attended_transfer(struct ast_json *json) int has_transferer_second_leg = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2251,6 +2269,15 @@ int ast_ari_validate_bridge_blind_transfer(struct ast_json *json) int has_result = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2417,6 +2444,15 @@ int ast_ari_validate_bridge_created(struct ast_json *json) int has_bridge = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeCreated field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2496,6 +2532,15 @@ int ast_ari_validate_bridge_destroyed(struct ast_json *json) int has_bridge = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeDestroyed field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2576,6 +2621,15 @@ int ast_ari_validate_bridge_merged(struct ast_json *json) int has_bridge_from = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeMerged field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2672,6 +2726,15 @@ int ast_ari_validate_channel_caller_id(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelCallerId field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2781,6 +2844,15 @@ int ast_ari_validate_channel_connected_line(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelConnectedLine field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2860,6 +2932,15 @@ int ast_ari_validate_channel_created(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelCreated field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -2941,6 +3022,15 @@ int ast_ari_validate_channel_destroyed(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelDestroyed field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3052,6 +3142,15 @@ int ast_ari_validate_channel_dialplan(struct ast_json *json) int has_dialplan_app_data = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelDialplan field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3163,6 +3262,15 @@ int ast_ari_validate_channel_dtmf_received(struct ast_json *json) int has_duration_ms = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelDtmfReceived field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3272,6 +3380,15 @@ int ast_ari_validate_channel_entered_bridge(struct ast_json *json) int has_bridge = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelEnteredBridge field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3360,6 +3477,15 @@ int ast_ari_validate_channel_hangup_request(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelHangupRequest field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3457,6 +3583,15 @@ int ast_ari_validate_channel_hold(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelHold field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3546,6 +3681,15 @@ int ast_ari_validate_channel_left_bridge(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelLeftBridge field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3640,6 +3784,15 @@ int ast_ari_validate_channel_state_change(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelStateChange field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3720,6 +3873,15 @@ int ast_ari_validate_channel_talking_finished(struct ast_json *json) int has_duration = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelTalkingFinished field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3814,6 +3976,15 @@ int ast_ari_validate_channel_talking_started(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelTalkingStarted field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3893,6 +4064,15 @@ int ast_ari_validate_channel_unhold(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelUnhold field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -3973,6 +4153,15 @@ int ast_ari_validate_channel_userevent(struct ast_json *json) int has_userevent = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelUserevent field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4095,6 +4284,15 @@ int ast_ari_validate_channel_varset(struct ast_json *json) int has_variable = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ChannelVarset field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4278,6 +4476,15 @@ int ast_ari_validate_contact_status_change(struct ast_json *json) int has_endpoint = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI ContactStatusChange field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4372,6 +4579,15 @@ int ast_ari_validate_device_state_changed(struct ast_json *json) int has_device_state = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI DeviceStateChanged field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4452,6 +4668,15 @@ int ast_ari_validate_dial(struct ast_json *json) int has_peer = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Dial field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4582,6 +4807,15 @@ int ast_ari_validate_endpoint_state_change(struct ast_json *json) int has_endpoint = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI EndpointStateChange field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4784,6 +5018,15 @@ int ast_ari_validate_event(struct ast_json *json) } for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Event field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -4976,6 +5219,15 @@ int ast_ari_validate_message(struct ast_json *json) } for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Message field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5015,6 +5267,15 @@ int ast_ari_validate_missing_params(struct ast_json *json) int has_params = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI MissingParams field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5146,6 +5407,15 @@ int ast_ari_validate_peer_status_change(struct ast_json *json) int has_peer = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI PeerStatusChange field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5240,6 +5510,15 @@ int ast_ari_validate_playback_continuing(struct ast_json *json) int has_playback = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI PlaybackContinuing field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5319,6 +5598,15 @@ int ast_ari_validate_playback_finished(struct ast_json *json) int has_playback = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI PlaybackFinished field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5398,6 +5686,15 @@ int ast_ari_validate_playback_started(struct ast_json *json) int has_playback = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI PlaybackStarted field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5477,6 +5774,15 @@ int ast_ari_validate_recording_failed(struct ast_json *json) int has_recording = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI RecordingFailed field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5556,6 +5862,15 @@ int ast_ari_validate_recording_finished(struct ast_json *json) int has_recording = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI RecordingFinished field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5635,6 +5950,15 @@ int ast_ari_validate_recording_started(struct ast_json *json) int has_recording = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI RecordingStarted field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5714,6 +6038,15 @@ int ast_ari_validate_stasis_end(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI StasisEnd field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5794,6 +6127,15 @@ int ast_ari_validate_stasis_start(struct ast_json *json) int has_channel = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI StasisStart field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; @@ -5898,6 +6240,15 @@ int ast_ari_validate_text_message_received(struct ast_json *json) int has_message = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI TextMessageReceived field asterisk_id failed validation\n"); + res = 0; + } + } else if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_type = 1; diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h index 2634528ba..0b08ce85e 100644 --- a/res/ari/ari_model_validators.h +++ b/res/ari/ari_model_validators.h @@ -1486,10 +1486,12 @@ ari_validator ast_ari_validate_application_fn(void); * - new_messages: int (required) * - old_messages: int (required) * ApplicationReplaced + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * BridgeAttendedTransfer + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1510,6 +1512,7 @@ ari_validator ast_ari_validate_application_fn(void); * - transferer_second_leg: Channel (required) * - transferer_second_leg_bridge: Bridge * BridgeBlindTransfer + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1522,22 +1525,26 @@ ari_validator ast_ari_validate_application_fn(void); * - result: string (required) * - transferee: Channel * BridgeCreated + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - bridge: Bridge (required) * BridgeDestroyed + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - bridge: Bridge (required) * BridgeMerged + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - bridge: Bridge (required) * - bridge_from: Bridge (required) * ChannelCallerId + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1545,16 +1552,19 @@ ari_validator ast_ari_validate_application_fn(void); * - caller_presentation_txt: string (required) * - channel: Channel (required) * ChannelConnectedLine + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * ChannelCreated + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * ChannelDestroyed + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1562,6 +1572,7 @@ ari_validator ast_ari_validate_application_fn(void); * - cause_txt: string (required) * - channel: Channel (required) * ChannelDialplan + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1569,6 +1580,7 @@ ari_validator ast_ari_validate_application_fn(void); * - dialplan_app: string (required) * - dialplan_app_data: string (required) * ChannelDtmfReceived + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1576,12 +1588,14 @@ ari_validator ast_ari_validate_application_fn(void); * - digit: string (required) * - duration_ms: int (required) * ChannelEnteredBridge + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - bridge: Bridge (required) * - channel: Channel * ChannelHangupRequest + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1589,39 +1603,46 @@ ari_validator ast_ari_validate_application_fn(void); * - channel: Channel (required) * - soft: boolean * ChannelHold + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * - musicclass: string * ChannelLeftBridge + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - bridge: Bridge (required) * - channel: Channel (required) * ChannelStateChange + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * ChannelTalkingFinished + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * - duration: int (required) * ChannelTalkingStarted + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * ChannelUnhold + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * ChannelUserevent + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1631,6 +1652,7 @@ ari_validator ast_ari_validate_application_fn(void); * - eventname: string (required) * - userevent: object (required) * ChannelVarset + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1643,17 +1665,20 @@ ari_validator ast_ari_validate_application_fn(void); * - roundtrip_usec: string * - uri: string (required) * ContactStatusChange + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - contact_info: ContactInfo (required) * - endpoint: Endpoint (required) * DeviceStateChanged + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - device_state: DeviceState (required) * Dial + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1664,17 +1689,21 @@ ari_validator ast_ari_validate_application_fn(void); * - forwarded: Channel * - peer: Channel (required) * EndpointStateChange + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - endpoint: Endpoint (required) * Event + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * Message + * - asterisk_id: string * - type: string (required) * MissingParams + * - asterisk_id: string * - type: string (required) * - params: List[string] (required) * Peer @@ -1684,47 +1713,56 @@ ari_validator ast_ari_validate_application_fn(void); * - port: string * - time: string * PeerStatusChange + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - endpoint: Endpoint (required) * - peer: Peer (required) * PlaybackContinuing + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - playback: Playback (required) * PlaybackFinished + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - playback: Playback (required) * PlaybackStarted + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - playback: Playback (required) * RecordingFailed + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - recording: LiveRecording (required) * RecordingFinished + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - recording: LiveRecording (required) * RecordingStarted + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - recording: LiveRecording (required) * StasisEnd + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date * - channel: Channel (required) * StasisStart + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date @@ -1732,6 +1770,7 @@ ari_validator ast_ari_validate_application_fn(void); * - channel: Channel (required) * - replace_channel: Channel * TextMessageReceived + * - asterisk_id: string * - type: string (required) * - application: string (required) * - timestamp: Date diff --git a/res/res_calendar.c b/res/res_calendar.c index 6f6f711b3..029ecebd0 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -436,6 +436,7 @@ static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *c cal->refresh = 3600; cal->timeframe = 60; cal->notify_waittime = 30000; + cal->fetch_again_at_reload = 0; for (v = ast_variable_browse(cfg, cat); v; v = v->next) { if (!strcasecmp(v->name, "autoreminder")) { @@ -457,6 +458,8 @@ static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *c ast_string_field_set(cal, notify_appdata, v->value); } else if (!strcasecmp(v->name, "refresh")) { cal->refresh = atoi(v->value); + } else if (!strcasecmp(v->name, "fetch_again_at_reload")) { + cal->fetch_again_at_reload = ast_true(v->value); } else if (!strcasecmp(v->name, "timeframe")) { cal->timeframe = atoi(v->value); } else if (!strcasecmp(v->name, "setvar")) { @@ -482,7 +485,7 @@ static struct ast_calendar *build_calendar(struct ast_config *cfg, const char *c } } - if (new_calendar) { + if (new_calendar || cal->fetch_again_at_reload) { cal->thread = AST_PTHREADT_NULL; ast_cond_init(&cal->unload, NULL); ao2_link(calendars, cal); diff --git a/res/res_fax.c b/res/res_fax.c index a2e179323..f602ba965 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -1415,11 +1415,13 @@ static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_de } json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}", - "type", "status", - "operation", (details->caps & AST_FAX_TECH_GATEWAY) ? "gateway" : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send", - "status", status, - "local_station_id", details->localstationid, - "filenames", json_filenames); + "type", "status", + "operation", (details->caps & AST_FAX_TECH_GATEWAY) + ? "gateway" + : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send", + "status", status, + "local_station_id", AST_JSON_UTF8_VALIDATE(details->localstationid), + "filenames", json_filenames); if (!json_object) { return -1; } @@ -1600,6 +1602,13 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det chancount = 1; + /* Make sure one or the other is set to avoid race condition */ + if (t38negotiated) { + details->caps |= AST_FAX_TECH_T38; + } else { + details->caps |= AST_FAX_TECH_AUDIO; + } + /* create the FAX session */ if (!(fax = fax_session_new(details, chan, reserved, token))) { ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n"); diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index d6eea3ce0..520fd7602 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -4284,6 +4284,7 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int int reconstruct = ntohl(rtpheader[0]); struct ast_sockaddr remote_address = { {0,} }; int ice; + unsigned int timestamp = ntohl(rtpheader[1]); /* Get fields from packet */ payload = (reconstruct & 0x7f0000) >> 16; @@ -4313,6 +4314,22 @@ static int bridge_p2p_rtp_write(struct ast_rtp_instance *instance, unsigned int return -1; } + /* If bridged peer is in dtmf, feed all packets to core until it finishes to avoid infinite dtmf */ + if (bridged->sending_digit) { + ast_debug(1, "Feeding packets to core until DTMF finishes\n"); + return -1; + } + + /* + * Even if we are no longer in dtmf, we could still be receiving + * re-transmissions of the last dtmf end still. Feed those to the + * core so they can be filtered accordingly. + */ + if (rtp->last_end_timestamp == timestamp) { + ast_debug(1, "Feeding packet with duplicate timestamp to core\n"); + return -1; + } + /* If the marker bit has been explicitly set turn it on */ if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) { mark = 1; diff --git a/res/stasis/app.c b/res/stasis/app.c index 6e5a396be..8bd1bc05a 100644 --- a/res/stasis/app.c +++ b/res/stasis/app.c @@ -455,7 +455,7 @@ static struct ast_json *channel_dialplan( "type", "ChannelDialplan", "timestamp", ast_json_timeval(*tv, NULL), "dialplan_app", new_snapshot->appl, - "dialplan_app_data", new_snapshot->data, + "dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->data), "channel", json_channel); } @@ -929,8 +929,15 @@ struct stasis_topic *ast_app_get_topic(struct stasis_app *app) void app_send(struct stasis_app *app, struct ast_json *message) { stasis_app_cb handler; + char eid[20]; RAII_VAR(void *, data, NULL, ao2_cleanup); + if (ast_json_object_set(message, "asterisk_id", ast_json_string_create( + ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)))) { + ast_log(AST_LOG_WARNING, "Failed to append EID to outgoing event %s\n", + ast_json_string_get(ast_json_object_get(message, "type"))); + } + /* Copy off mutable state with lock held */ { SCOPED_AO2LOCK(lock, app); diff --git a/rest-api/api-docs/events.json b/rest-api/api-docs/events.json index ca2616101..4ef1d21a4 100644 --- a/rest-api/api-docs/events.json +++ b/rest-api/api-docs/events.json @@ -110,6 +110,11 @@ "type": "string", "required": true, "description": "Indicates the type of this message." + }, + "asterisk_id": { + "type": "string", + "required": false, + "description": "The unique ID for the Asterisk instance that raised this event." } }, "subTypes": [ diff --git a/tests/test_json.c b/tests/test_json.c index 915578128..7362a6127 100644 --- a/tests/test_json.c +++ b/tests/test_json.c @@ -1598,11 +1598,26 @@ AST_TEST_DEFINE(json_test_clever_circle) return AST_TEST_PASS; } -AST_TEST_DEFINE(json_test_name_number) +static int test_name_number(const char *name, const char *number) { - RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref); - RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref); + int res; + struct ast_json *uut; + struct ast_json *expected; + + expected = ast_json_pack("{s: s, s: s}", + "name", name ?: "", + "number", number ?: ""); + uut = ast_json_name_number(name, number); + + res = ast_json_equal(expected, uut); + ast_json_unref(expected); + ast_json_unref(uut); + return res; +} + +AST_TEST_DEFINE(json_test_name_number) +{ switch (cmd) { case TEST_INIT: info->name = "name_number"; @@ -1614,15 +1629,10 @@ AST_TEST_DEFINE(json_test_name_number) break; } - ast_test_validate(test, NULL == ast_json_name_number("name", NULL)); - ast_test_validate(test, NULL == ast_json_name_number(NULL, "1234")); - ast_test_validate(test, NULL == ast_json_name_number(NULL, NULL)); - - expected = ast_json_pack("{s: s, s: s}", - "name", "Jenny", - "number", "867-5309"); - uut = ast_json_name_number("Jenny", "867-5309"); - ast_test_validate(test, ast_json_equal(expected, uut)); + ast_test_validate(test, test_name_number("name", NULL)); + ast_test_validate(test, test_name_number(NULL, "1234")); + ast_test_validate(test, test_name_number(NULL, NULL)); + ast_test_validate(test, test_name_number("Jenny", "867-5309")); return AST_TEST_PASS; } diff --git a/tests/test_res_stasis.c b/tests/test_res_stasis.c index 4e28d44c6..459890373 100644 --- a/tests/test_res_stasis.c +++ b/tests/test_res_stasis.c @@ -138,6 +138,7 @@ AST_TEST_DEFINE(app_replaced) RAII_VAR(struct ast_json *, expected_message1, NULL, ast_json_unref); RAII_VAR(struct ast_json *, message, NULL, ast_json_unref); RAII_VAR(struct ast_json *, expected_message2, NULL, ast_json_unref); + char eid[20]; int res; switch (cmd) { @@ -158,9 +159,10 @@ AST_TEST_DEFINE(app_replaced) stasis_app_register(app_name, test_handler, app_data1); stasis_app_register(app_name, test_handler, app_data2); - expected_message1 = ast_json_pack("[{s: s, s: s}]", + expected_message1 = ast_json_pack("[{s: s, s: s, s: s}]", "type", "ApplicationReplaced", - "application", app_name); + "application", app_name, + "asterisk_id", ast_eid_to_str(eid, sizeof(eid), &ast_eid_default)); message = ast_json_pack("{ s: o }", "test-message", ast_json_null()); expected_message2 = ast_json_pack("[o]", ast_json_ref(message)); diff --git a/third-party/Makefile.rules b/third-party/Makefile.rules index 92e4ebc85..4f804dd0e 100644 --- a/third-party/Makefile.rules +++ b/third-party/Makefile.rules @@ -13,18 +13,6 @@ QUIET_CONFIGURE= REALLY_QUIET= endif -DOWNLOAD := $(shell which wget 2>/dev/null) -DOWNLOAD := $(if $(DOWNLOAD),$(DOWNLOAD) -O- ,) - -ifeq ($(DOWNLOAD),) -DOWNLOAD := $(shell which curl 2>/dev/null) -DOWNLOAD := $(if $(DOWNLOAD), $(DOWNLOAD) -L ,) -endif - -ifeq ($(DOWNLOAD),) -DOWNLOAD := echo "No download program available" ; exit 1; -endif - export SUBMAKE export ECHO_PREFIX export CMD_PREFIX @@ -34,3 +22,8 @@ export ASTTOPDIR export ASTSBINDIR export DESTDIR export ASTDATADIR +export TAR +export PATCH +export SED +export NM +export DOWNLOAD diff --git a/third-party/configure.m4 b/third-party/configure.m4 new file mode 100644 index 000000000..635446638 --- /dev/null +++ b/third-party/configure.m4 @@ -0,0 +1,7 @@ + + +AC_DEFUN([THIRD_PARTY_CONFIGURE], +[ + PJPROJECT_CONFIGURE() +]) + diff --git a/third-party/pjproject/Makefile b/third-party/pjproject/Makefile index bb98a09e3..65875224f 100644 --- a/third-party/pjproject/Makefile +++ b/third-party/pjproject/Makefile @@ -7,8 +7,6 @@ SPECIAL_TARGETS := ifneq ($(findstring configure,$(MAKECMDGOALS))$(findstring echo_cflags,$(MAKECMDGOALS)),) # Run from $(ASTTOPDIR)/configure SPECIAL_TARGETS += configure - include ../Makefile.rules - include Makefile.rules endif ifeq ($(findstring echo_cflags,$(MAKECMDGOALS)),echo_cflags) @@ -19,8 +17,10 @@ endif ifeq ($(findstring clean,$(MAKECMDGOALS)),clean) # clean or distclean SPECIAL_TARGETS += clean - include ../Makefile.rules - include Makefile.rules +endif + +ifneq ($(wildcard ../../makeopts),) + include ../../makeopts endif ifeq ($(SPECIAL_TARGETS),) @@ -28,17 +28,17 @@ ifeq ($(SPECIAL_TARGETS),) ifeq ($(wildcard ../../makeopts),) $(error ASTTOPDIR/configure hasn't been run) endif - include ../../makeopts ifeq ($(PJPROJECT_BUNDLED),yes) - -include ../../menuselect.makeopts - include ../Makefile.rules + ifneq ($(wildcard ../../menuselect.makeopts),) + include ../../menuselect.makeopts + else + $(warning ASTTOPDIR/menuselect hasn't been run yet. Can't find debug options.) + endif all: _all install: _install - include ../../Makefile.rules - include Makefile.rules include source/user.mak include source/build.mak CF := $(filter-out -W%,$(CC_CFLAGS)) @@ -66,25 +66,25 @@ ifeq ($(SPECIAL_TARGETS),) endif endif +include ../../Makefile.rules +include ../Makefile.rules +include Makefile.rules + ECHO_PREFIX := $(ECHO_PREFIX) echo '[pjproject] ' -ifndef $(TMPDIR) - ifneq ($(wildcard /tmp),) - TMPDIR=/tmp - else - TMPDIR=. - endif -endif +_all: $(TARGETS) + +EXTERNALS_CACHE_DIR ?= $(or $(TMPDIR),$(wildcard /tmp),.) -$(TMPDIR)/pjproject-$(PJPROJECT_VERSION).tar.bz2 : ../versions.mak - $(ECHO_PREFIX) Downloading $@ with $(DOWNLOAD) - $(CMD_PREFIX) $(DOWNLOAD) $(PJPROJECT_URL)/$(@F) > $@ +$(EXTERNALS_CACHE_DIR)/pjproject-$(PJPROJECT_VERSION).tar.bz2 : ../versions.mak + $(ECHO_PREFIX) Downloading $(PJPROJECT_URL)/$(@F) to $@ + $(CMD_PREFIX) $(DOWNLOAD_TO_STDOUT) $(PJPROJECT_URL)/$(@F) > $@ -source/.unpacked: $(TMPDIR)/pjproject-$(PJPROJECT_VERSION).tar.bz2 +source/.unpacked: $(EXTERNALS_CACHE_DIR)/pjproject-$(PJPROJECT_VERSION).tar.bz2 $(ECHO_PREFIX) Unpacking $< -@rm -rf source >/dev/null 2>&1 -@mkdir source >/dev/null 2>&1 - $(CMD_PREFIX) tar --strip-components=1 -C source -xjf $< + $(CMD_PREFIX) $(TAR) --strip-components=1 -C source -xjf $< $(ECHO_PREFIX) Applying patches $(CMD_PREFIX) ./apply_patches $(QUIET_CONFIGURE) ./patches ./source -@touch source/.unpacked @@ -99,8 +99,8 @@ source/pjlib/include/pj/%.h : ./patches/%.h build.mak: source/.unpacked $(addprefix source/pjlib/include/pj/,$(notdir $(wildcard ./patches/*.h))) source/user.mak Makefile.rules $(ECHO_PREFIX) Configuring with $(PJPROJECT_CONFIG_OPTS) - $(CMD_PREFIX) (cd source ; autoconf aconfigure.ac > aconfigure && ./aconfigure $(QUIET_CONFIGURE) $(PJPROJECT_CONFIG_OPTS)) - @sed -r -e "/prefix|export PJ_SHARED_LIBRARIES|MACHINE_NAME|OS_NAME|HOST_NAME|CC_NAME|CROSS_COMPILE|LINUX_POLL/d" source/build.mak > build.mak + $(CMD_PREFIX) (cd source ; ./aconfigure $(QUIET_CONFIGURE) $(PJPROJECT_CONFIG_OPTS)) + $(SED) -r -e "/prefix|export PJ_SHARED_LIBRARIES|MACHINE_NAME|OS_NAME|HOST_NAME|CC_NAME|CROSS_COMPILE|LINUX_POLL/d" source/build.mak > build.mak configure: build.mak @@ -128,7 +128,7 @@ $(LIB_FILES): $(PJLIB_UTIL_LIB_FILES) pjproject.symbols: $(ALL_LIB_FILES) $(ECHO_PREFIX) Generating symbols - $(CMD_PREFIX) nm -Pog $(ALL_LIB_FILES) | sed -n -r -e "s/.+: ([pP][jJ][^ ]+) .+/\1/gp" | sort -u > pjproject.symbols + $(CMD_PREFIX) $(NM) -Pog $(PJ_LIB_FILES) | $(SED) -n -r -e "s/.+: ([pP][jJ][^ ]+) .+/\1/gp" | sort -u > pjproject.symbols source/pjsip-apps/src/asterisk_malloc_debug.c: patches/asterisk_malloc_debug.c $(ECHO_PREFIX) Copying $< to $@ @@ -155,8 +155,6 @@ source/pjsip-apps/src/python/_pjsua.so: source/pjsip-apps/src/python/_pjsua.o $(ECHO_PREFIX) Linking python bindings $(@F) $(CMD_PREFIX) gcc -shared -pthread -o $@ $< $(LDFLAGS) $(PJ_LDFLAGS) $(APP_LDLIBS) $(PYTHONDEV_LIB) $(REALLY_QUIET) -_all: $(TARGETS) - _install: _all @if [ ! -d "$(DESTDIR)$(ASTDATADIR)/third-party/pjproject" ]; then \ $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/third-party/pjproject"; \ @@ -188,4 +186,3 @@ clean: distclean: $(ECHO_PREFIX) Distcleaning -$(CMD_PREFIX) rm -rf source pjproject.symbols pjproject-*.tar.bz2 build.mak .rebuild_needed - diff --git a/third-party/pjproject/apply_patches b/third-party/pjproject/apply_patches index 5dfdd2a3c..c28f40301 100755 --- a/third-party/pjproject/apply_patches +++ b/third-party/pjproject/apply_patches @@ -5,6 +5,8 @@ if [ "$1" = "-q" ] ; then shift fi +PATCH=${PATCH:-patch} + patchdir=${1:?You must supply a patches directory} sourcedir=${2?:You must supply a source directory} @@ -27,12 +29,12 @@ if [ ! "$(ls -A $patchdir/*.patch 2>/dev/null)" ] ; then fi for patchfile in $patchdir/*.patch ; do - patch -d $sourcedir -p1 -s -r- -f -N --dry-run -i "$patchfile" || (echo "Patchfile $(basename $patchfile) failed to apply" >&2 ; exit 1) || exit 1 + ${PATCH} -d $sourcedir -p1 -s -r- -f -N --dry-run -i "$patchfile" || (echo "Patchfile $(basename $patchfile) failed to apply" >&2 ; exit 1) || exit 1 done for patchfile in "$patchdir"/*.patch ; do [ -z $quiet ] && echo "Applying patch $(basename $patchfile)" - patch -d "$sourcedir" -p1 -s -i "$patchfile" || exit 1 + ${PATCH} -d "$sourcedir" -p1 -s -i "$patchfile" || exit 1 done exit 0 diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4 index 7a079f657..7b62c0f16 100644 --- a/third-party/pjproject/configure.m4 +++ b/third-party/pjproject/configure.m4 @@ -1,49 +1,72 @@ -AC_DEFUN([PJPROJECT_SYMBOL_CHECK], +AC_DEFUN([_PJPROJECT_CONFIGURE], [ - $1_INCLUDE="$PJPROJECT_INCLUDE" - AC_MSG_CHECKING([for $2 declared in $3]) - - saved_cpp="$CPPFLAGS" - CPPFLAGS="$PJPROJECT_INCLUDE" - AC_EGREP_HEADER($2, $3, [ - AC_MSG_RESULT(yes) - PBX_$1=1 - AC_DEFINE([HAVE_$1], 1, [Define if your system has $2 declared.]) - ], [ - AC_MSG_RESULT(no) - ]) - - CPPGLAGS="$saved_cpp" - $1_INCLUDE="$PJPROJECT_INCLUDE" -]) + if test "${ac_mandatory_list#*PJPROJECT*}" != "$ac_mandatory_list" ; then + AC_MSG_ERROR(--with-pjproject and --with-pjproject-bundled can't both be specified) + fi + + ac_mandatory_list="$ac_mandatory_list PJPROJECT" + PJPROJECT_DIR="${ac_top_build_prefix}third-party/pjproject" -AC_DEFUN([PJPROJECT_CONFIGURE], -[ AC_MSG_CHECKING(for embedded pjproject (may have to download)) AC_MSG_RESULT(configuring) - ${GNU_MAKE} --quiet --no-print-directory -C $1 configure + + if test "x${DOWNLOAD_TO_STDOUT}" = "x" ; then + AC_MSG_ERROR(A download utility (wget, curl or fetch) is required to download bundled pjproject) + fi + if test "${BZIP2}" = ":" ; then + AC_MSG_ERROR(bzip2 is required to extract the pjproject tar file) + fi + if test "${TAR}" = ":" ; then + AC_MSG_ERROR(tar is required to extract the pjproject tar file) + fi + if test "${PATCH}" = ":" ; then + AC_MSG_ERROR(patch is required to configure bundled pjproject) + fi + if test "${SED}" = ":" ; then + AC_MSG_ERROR(sed is required to configure bundled pjproject) + fi + if test "${NM}" = ":" ; then + AC_MSG_ERROR(nm is required to build bundled pjproject) + fi + + export TAR PATCH SED NM EXTERNALS_CACHE_DIR DOWNLOAD_TO_STDOUT + ${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} configure if test $? -ne 0 ; then AC_MSG_RESULT(failed) - AC_MSG_NOTICE(Unable to configure $1) - AC_MSG_ERROR(Run "${GNU_MAKE} -C $1 NOISY_BUILD=yes configure" to see error details.) + AC_MSG_NOTICE(Unable to configure ${PJPROJECT_DIR}) + AC_MSG_ERROR(Run "${GNU_MAKE} -C ${PJPROJECT_DIR} NOISY_BUILD=yes configure" to see error details.) fi - PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C $1 echo_cflags) + AC_MSG_CHECKING(for bundled pjproject) + + PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} echo_cflags) PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE" PBX_PJPROJECT=1 - PJPROJECT_BUNDLED=yes + AC_DEFINE([HAVE_PJPROJECT], 1, [Define if your system has PJPROJECT]) AC_DEFINE([HAVE_PJPROJECT_BUNDLED], 1, [Define if your system has PJPROJECT_BUNDLED]) - AC_MSG_CHECKING(for embedded pjproject) - AC_MSG_RESULT(yes) - PJPROJECT_SYMBOL_CHECK([PJSIP_DLG_CREATE_UAS_AND_INC_LOCK], [pjsip_dlg_create_uas_and_inc_lock], [pjsip.h]) - PJPROJECT_SYMBOL_CHECK([PJ_TRANSACTION_GRP_LOCK], [pjsip_tsx_create_uac2], [pjsip.h]) - PJPROJECT_SYMBOL_CHECK([PJSIP_REPLACE_MEDIA_STREAM], [PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE], [pjmedia.h]) - PJPROJECT_SYMBOL_CHECK([PJSIP_GET_DEST_INFO], [pjsip_get_dest_info], [pjsip.h]) - PJPROJECT_SYMBOL_CHECK([PJ_SSL_CERT_LOAD_FROM_FILES2], [pj_ssl_cert_load_from_files2], [pjlib.h]) - PJPROJECT_SYMBOL_CHECK([PJSIP_EXTERNAL_RESOLVER], [pjsip_endpt_set_ext_resolver], [pjsip.h]) + AC_DEFINE([HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK], 1, [Define if your system has pjsip_dlg_create_uas_and_inc_lock declared.]) + AC_DEFINE([HAVE_PJ_TRANSACTION_GRP_LOCK], 1, [Define if your system has pjsip_tsx_create_uac2 declared.]) + AC_DEFINE([HAVE_PJSIP_REPLACE_MEDIA_STREAM], 1, [Define if your system has PJSIP_REPLACE_MEDIA_STREAM declared]) + AC_DEFINE([HAVE_PJSIP_GET_DEST_INFO], 1, [Define if your system has pjsip_get_dest_info declared.]) + AC_DEFINE([HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2], 1, [Define if your system has pj_ssl_cert_load_from_files2 declared.]) + AC_DEFINE([HAVE_PJSIP_EXTERNAL_RESOLVER], 1, [Define if your system has pjsip_endpt_set_ext_resolver declared.]) AC_DEFINE([HAVE_PJSIP_TLS_TRANSPORT_PROTO], 1, [Define if your system has PJSIP_TLS_TRANSPORT_PROTO]) AC_DEFINE([HAVE_PJSIP_EVSUB_GRP_LOCK], 1, [Define if your system has PJSIP_EVSUB_GRP_LOCK]) AC_DEFINE([HAVE_PJSIP_INV_SESSION_REF], 1, [Define if your system has PJSIP_INV_SESSION_REF]) + + AC_SUBST([PJPROJECT_BUNDLED]) + AC_SUBST([PJPROJECT_DIR]) + AC_SUBST([PBX_PJPROJECT]) + AC_SUBST([PJPROJECT_LIB]) + AC_SUBST([PJPROJECT_INCLUDE]) + AC_MSG_RESULT(yes) +]) + +AC_DEFUN([PJPROJECT_CONFIGURE], +[ + if test "$PJPROJECT_BUNDLED" = "yes" ; then + _PJPROJECT_CONFIGURE() + fi ]) diff --git a/third-party/pjproject/patches/0005-Re-1969-Fix-crash-on-using-an-already-destroyed-SSL-.patch b/third-party/pjproject/patches/0005-Re-1969-Fix-crash-on-using-an-already-destroyed-SSL-.patch new file mode 100644 index 000000000..551e61ab6 --- /dev/null +++ b/third-party/pjproject/patches/0005-Re-1969-Fix-crash-on-using-an-already-destroyed-SSL-.patch @@ -0,0 +1,164 @@ +From 9e67e0d5c3fdc747530a956038b374fca4748b76 Mon Sep 17 00:00:00 2001 +From: riza <riza@localhost> +Date: Thu, 13 Oct 2016 09:02:50 +0000 +Subject: [PATCH 1/4] Re #1969: Fix crash on using an already destroyed SSL + socket. + +--- + pjlib/src/pj/ssl_sock_ossl.c | 66 ++++++++++++++++++++++++++++---------------- + 1 file changed, 42 insertions(+), 24 deletions(-) + +diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c +index fa0db2d..ceab67a 100644 +--- a/pjlib/src/pj/ssl_sock_ossl.c ++++ b/pjlib/src/pj/ssl_sock_ossl.c +@@ -822,7 +822,10 @@ static void close_sockets(pj_ssl_sock_t *ssock) + pj_lock_acquire(ssock->write_mutex); + asock = ssock->asock; + if (asock) { +- ssock->asock = NULL; ++ // Don't set ssock->asock to NULL, as it may trigger assertion in ++ // send operation. This should be safe as active socket will simply ++ // return PJ_EINVALIDOP on any operation if it is already closed. ++ //ssock->asock = NULL; + ssock->sock = PJ_INVALID_SOCKET; + } + sock = ssock->sock; +@@ -841,9 +844,9 @@ static void close_sockets(pj_ssl_sock_t *ssock) + /* Reset SSL socket state */ + static void reset_ssl_sock_state(pj_ssl_sock_t *ssock) + { ++ pj_lock_acquire(ssock->write_mutex); + ssock->ssl_state = SSL_STATE_NULL; +- +- destroy_ssl(ssock); ++ pj_lock_release(ssock->write_mutex); + + close_sockets(ssock); + +@@ -1612,6 +1615,21 @@ static pj_status_t do_handshake(pj_ssl_sock_t *ssock) + return PJ_EPENDING; + } + ++static void ssl_on_destroy(void *arg) ++{ ++ pj_pool_t *pool = NULL; ++ pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)arg; ++ ++ destroy_ssl(ssock); ++ ++ pj_lock_destroy(ssock->write_mutex); ++ ++ pool = ssock->pool; ++ ssock->pool = NULL; ++ if (pool) ++ pj_pool_release(pool); ++} ++ + + /* + ******************************************************************* +@@ -1830,7 +1848,7 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, + + /* Create new SSL socket instance */ + status = pj_ssl_sock_create(ssock_parent->pool, +- &ssock_parent->newsock_param, &ssock); ++ &ssock_parent->newsock_param, &ssock); + if (status != PJ_SUCCESS) + goto on_return; + +@@ -1906,12 +1924,10 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, + if (status != PJ_SUCCESS) + goto on_return; + +- /* Temporarily add ref the group lock until active socket creation, +- * to make sure that group lock is destroyed if the active socket +- * creation fails. +- */ + pj_grp_lock_add_ref(glock); + asock_cfg.grp_lock = ssock->param.grp_lock = glock; ++ pj_grp_lock_add_handler(ssock->param.grp_lock, ssock->pool, ssock, ++ ssl_on_destroy); + } + + pj_bzero(&asock_cb, sizeof(asock_cb)); +@@ -1927,11 +1943,6 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, + ssock, + &ssock->asock); + +- /* This will destroy the group lock if active socket creation fails */ +- if (asock_cfg.grp_lock) { +- pj_grp_lock_dec_ref(asock_cfg.grp_lock); +- } +- + if (status != PJ_SUCCESS) + goto on_return; + +@@ -2251,17 +2262,26 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool, + /* Create secure socket mutex */ + status = pj_lock_create_recursive_mutex(pool, pool->obj_name, + &ssock->write_mutex); +- if (status != PJ_SUCCESS) ++ if (status != PJ_SUCCESS) { ++ pj_pool_release(pool); + return status; ++ } + + /* Init secure socket param */ + pj_ssl_sock_param_copy(pool, &ssock->param, param); ++ ++ if (ssock->param.grp_lock) { ++ pj_grp_lock_add_ref(ssock->param.grp_lock); ++ pj_grp_lock_add_handler(ssock->param.grp_lock, pool, ssock, ++ ssl_on_destroy); ++ } ++ + ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3; + if (!ssock->param.timer_heap) { + PJ_LOG(3,(ssock->pool->obj_name, "Warning: timer heap is not " + "available. It is recommended to supply one to avoid " +- "a race condition if more than one worker threads " +- "are used.")); ++ "a race condition if more than one worker threads " ++ "are used.")); + } + + /* Finally */ +@@ -2277,8 +2297,6 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool, + */ + PJ_DEF(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock) + { +- pj_pool_t *pool; +- + PJ_ASSERT_RETURN(ssock, PJ_EINVAL); + + if (!ssock->pool) +@@ -2290,12 +2308,11 @@ PJ_DEF(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock) + } + + reset_ssl_sock_state(ssock); +- pj_lock_destroy(ssock->write_mutex); +- +- pool = ssock->pool; +- ssock->pool = NULL; +- if (pool) +- pj_pool_release(pool); ++ if (ssock->param.grp_lock) { ++ pj_grp_lock_dec_ref(ssock->param.grp_lock); ++ } else { ++ ssl_on_destroy(ssock); ++ } + + return PJ_SUCCESS; + } +@@ -2782,6 +2799,7 @@ pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock, + + /* Start accepting */ + pj_ssl_sock_param_copy(pool, &ssock->newsock_param, newsock_param); ++ ssock->newsock_param.grp_lock = NULL; + status = pj_activesock_start_accept(ssock->asock, pool); + if (status != PJ_SUCCESS) + goto on_error; +-- +2.7.4 + |