diff options
26 files changed, 289 insertions, 740 deletions
@@ -12,6 +12,11 @@ --- Functionality changes from Asterisk 13.9.0 to Asterisk 13.10.0 ----------- ------------------------------------------------------------------------------ +Core +------------------ + * A channel variable FORWARDERNAME is now set which indicates which channel + was responsible for a forwarding requests received on dial attempt. + func_odbc ------------------ * Added new global option "single_db_connection". @@ -63,6 +68,12 @@ res_pjsip_info_empty Some SBCs will terminate a call if their empty INFO packets are not responded to within a predefined time. +res_odbc +------------------ + * A new option has been added, 'max_connections', which sets the maximum number + of concurrent connections to the database. This option defaults to 1 which + returns the behavior to that of Asterisk 13.7 and prior. + app_confbridge ------------------ * Added a bridge profile option called regcontext that allows you to diff --git a/apps/app_dial.c b/apps/app_dial.c index bc4f8a574..c05aecaf9 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -834,6 +834,7 @@ static void do_forward(struct chanlist *o, struct cause_args *num, struct ast_party_id *forced_clid, struct ast_party_id *stored_clid) { char tmpchan[256]; + char forwarder[AST_CHANNEL_NAME]; struct ast_channel *original = o->chan; struct ast_channel *c = o->chan; /* the winner */ struct ast_channel *in = num->chan; /* the input channel */ @@ -842,6 +843,7 @@ static void do_forward(struct chanlist *o, struct cause_args *num, int cause; struct ast_party_caller caller; + ast_copy_string(forwarder, ast_channel_name(c), sizeof(forwarder)); ast_copy_string(tmpchan, ast_channel_call_forward(c), sizeof(tmpchan)); if ((stuff = strchr(tmpchan, '/'))) { *stuff++ = '\0'; @@ -893,6 +895,7 @@ static void do_forward(struct chanlist *o, struct cause_args *num, ast_channel_lock_both(in, o->chan); ast_channel_inherit_variables(in, o->chan); ast_channel_datastore_inherit(in, o->chan); + pbx_builtin_setvar_helper(o->chan, "FORWARDERNAME", forwarder); ast_max_forwards_decrement(o->chan); ast_channel_unlock(in); ast_channel_unlock(o->chan); diff --git a/apps/app_queue.c b/apps/app_queue.c index dbd83938d..3d22f9821 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -4827,16 +4827,22 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte continue; } else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) { struct ast_channel *original = o->chan; + char forwarder[AST_CHANNEL_NAME]; char tmpchan[256]; char *stuff; char *tech; ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan)); + ast_copy_string(forwarder, ast_channel_name(o->chan), sizeof(forwarder)); if ((stuff = strchr(tmpchan, '/'))) { *stuff++ = '\0'; tech = tmpchan; } else { - snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), ast_channel_context(o->chan)); + const char *forward_context; + ast_channel_lock(o->chan); + forward_context = pbx_builtin_getvar_helper(o->chan, "FORWARD_CONTEXT"); + snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), forward_context ? forward_context : ast_channel_context(o->chan)); + ast_channel_unlock(o->chan); stuff = tmpchan; tech = "Local"; } @@ -4868,6 +4874,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte ast_channel_lock_both(o->chan, in); ast_channel_inherit_variables(in, o->chan); ast_channel_datastore_inherit(in, o->chan); + pbx_builtin_setvar_helper(o->chan, "FORWARDERNAME", forwarder); ast_max_forwards_decrement(o->chan); if (o->pending_connected_update) { diff --git a/cdr/cdr_custom.c b/cdr/cdr_custom.c index df763639f..6ef2cb094 100644 --- a/cdr/cdr_custom.c +++ b/cdr/cdr_custom.c @@ -81,8 +81,10 @@ static AST_RWLIST_HEAD_STATIC(sinks, cdr_custom_config); static void free_config(void) { struct cdr_custom_config *sink; + while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) { ast_mutex_destroy(&sink->lock); + ast_string_field_free_memory(sink); ast_free(sink); } } diff --git a/cdr/cdr_syslog.c b/cdr/cdr_syslog.c index 458721aa8..c1169a35c 100644 --- a/cdr/cdr_syslog.c +++ b/cdr/cdr_syslog.c @@ -76,8 +76,10 @@ static AST_RWLIST_HEAD_STATIC(sinks, cdr_syslog_config); static void free_config(void) { struct cdr_syslog_config *sink; + while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) { ast_mutex_destroy(&sink->lock); + ast_string_field_free_memory(sink); ast_free(sink); } } diff --git a/cel/cel_custom.c b/cel/cel_custom.c index edb009686..0b2ac764f 100644 --- a/cel/cel_custom.c +++ b/cel/cel_custom.c @@ -71,8 +71,10 @@ static AST_RWLIST_HEAD_STATIC(sinks, cel_config); static void free_config(void) { struct cel_config *sink; + while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) { ast_mutex_destroy(&sink->lock); + ast_string_field_free_memory(sink); ast_free(sink); } } diff --git a/configs/samples/res_odbc.conf.sample b/configs/samples/res_odbc.conf.sample index 66659ae42..a21e96d07 100644 --- a/configs/samples/res_odbc.conf.sample +++ b/configs/samples/res_odbc.conf.sample @@ -51,6 +51,11 @@ pre-connect => yes ; that we should attempt? ;limit => 5 ; +; The maximum number of connections to have open at any given time. +; This defaults to 1 and it is highly recommended to only set this higher +; if using a version of UnixODBC greater than 2.3.1. +;max_connections => 20 +; ; When the channel is destroyed, should any uncommitted open transactions ; automatically be committed? ;forcecommit => no diff --git a/contrib/ast-db-manage/config/versions/81b01a191a46_pjsip_add_contact_reg_server.py b/contrib/ast-db-manage/config/versions/81b01a191a46_pjsip_add_contact_reg_server.py index c25fc7233..0318b9a4f 100644 --- a/contrib/ast-db-manage/config/versions/81b01a191a46_pjsip_add_contact_reg_server.py +++ b/contrib/ast-db-manage/config/versions/81b01a191a46_pjsip_add_contact_reg_server.py @@ -16,7 +16,7 @@ import sqlalchemy as sa def upgrade(): op.add_column('ps_contacts', sa.Column('reg_server', sa.String(20))) - op.drop_constraint(UniqueConstraint('id'), 'ps_contacts', type_='unique') + op.drop_constraint('id', 'ps_contacts', type_='unique') op.create_unique_constraint('ps_contacts_uq', 'ps_contacts', ['id','reg_server']) def downgrade(): diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 4baae3cc5..543988dde 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -2162,9 +2162,10 @@ int bridge_channel_internal_push_full(struct ast_bridge_channel *bridge_channel, ast_bridge_publish_enter(bridge, bridge_channel->chan, swap ? swap->chan : NULL); - /* Clear any BLINDTRANSFER and ATTENDEDTRANSFER since the transfer has completed. */ + /* Clear any BLINDTRANSFER,ATTENDEDTRANSFER and FORWARDERNAME since the transfer has completed. */ pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", NULL); pbx_builtin_setvar_helper(bridge_channel->chan, "ATTENDEDTRANSFER", NULL); + pbx_builtin_setvar_helper(bridge_channel->chan, "FORWARDERNAME", NULL); /* Wake up the bridge channel thread to reevaluate any interval timers. */ ast_queue_frame(bridge_channel->chan, &ast_null_frame); diff --git a/main/channel.c b/main/channel.c index 4ed1f8b8a..327ec64a6 100644 --- a/main/channel.c +++ b/main/channel.c @@ -5663,6 +5663,7 @@ static void call_forward_inherit(struct ast_channel *new_chan, struct ast_channe struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_channel *orig, int *timeout, struct ast_format_cap *cap, struct outgoing_helper *oh, int *outstate) { char tmpchan[256]; + char forwarder[AST_CHANNEL_NAME]; struct ast_channel *new_chan = NULL; char *data, *type; int cause = 0; @@ -5670,6 +5671,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan /* gather data and request the new forward channel */ ast_copy_string(tmpchan, ast_channel_call_forward(orig), sizeof(tmpchan)); + ast_copy_string(forwarder, ast_channel_name(orig), sizeof(forwarder)); if ((data = strchr(tmpchan, '/'))) { *data++ = '\0'; type = tmpchan; @@ -5713,6 +5715,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan ast_set_flag(ast_channel_flags(new_chan), AST_FLAG_ORIGINATED); ast_channel_lock_both(orig, new_chan); + pbx_builtin_setvar_helper(new_chan, "FORWARDERNAME", forwarder); ast_party_connected_line_copy(ast_channel_connected(new_chan), ast_channel_connected(orig)); ast_party_redirecting_copy(ast_channel_redirecting(new_chan), ast_channel_redirecting(orig)); ast_channel_req_accountcodes(new_chan, orig, AST_CHANNEL_REQUESTOR_REPLACEMENT); diff --git a/main/dial.c b/main/dial.c index fe592033e..ffa440546 100644 --- a/main/dial.c +++ b/main/dial.c @@ -411,16 +411,24 @@ int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_ } /*! \brief Helper function that does the beginning dialing per-appended channel */ -static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async, const char *predial_string) +static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_channel *chan, int async, const char *predial_string, struct ast_channel *forwarder_chan) { char numsubst[AST_MAX_EXTENSION]; int res = 1; + char forwarder[AST_CHANNEL_NAME]; /* If no owner channel exists yet execute pre-run */ if (!channel->owner && begin_dial_prerun(channel, chan, NULL, predial_string)) { return 0; } + if (forwarder_chan) { + ast_copy_string(forwarder, ast_channel_name(forwarder_chan), sizeof(forwarder)); + ast_channel_lock(channel->owner); + pbx_builtin_setvar_helper(channel->owner, "FORWARDERNAME", forwarder); + ast_channel_unlock(channel->owner); + } + /* Copy device string over */ ast_copy_string(numsubst, channel->device, sizeof(numsubst)); @@ -451,7 +459,7 @@ static int begin_dial(struct ast_dial *dial, struct ast_channel *chan, int async /* Iterate through channel list, requesting and calling each one */ AST_LIST_LOCK(&dial->channels); AST_LIST_TRAVERSE(&dial->channels, channel, list) { - success += begin_dial_channel(channel, chan, async, predial_string); + success += begin_dial_channel(channel, chan, async, predial_string, NULL); } AST_LIST_UNLOCK(&dial->channels); @@ -507,7 +515,7 @@ static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *c channel->owner = NULL; /* Finally give it a go... send it out into the world */ - begin_dial_channel(channel, chan, chan ? 0 : 1, predial_string); + begin_dial_channel(channel, chan, chan ? 0 : 1, predial_string, original); ast_channel_publish_dial_forward(chan, original, channel->owner, NULL, "CANCEL", ast_channel_call_forward(original)); diff --git a/main/logger.c b/main/logger.c index 9f03b4efa..a70b6d15e 100644 --- a/main/logger.c +++ b/main/logger.c @@ -168,6 +168,7 @@ static void logmsg_free(struct logmsg *msg) if (msg->callid) { ast_callid_unref(msg->callid); } + ast_string_field_free_memory(msg); ast_free(msg); } diff --git a/res/res_odbc.c b/res/res_odbc.c index 17b7a76c8..b2204ff09 100644 --- a/res/res_odbc.c +++ b/res/res_odbc.c @@ -78,10 +78,19 @@ struct odbc_class unsigned int forcecommit:1; /*!< Should uncommitted transactions be auto-committed on handle release? */ unsigned int isolation; /*!< Flags for how the DB should deal with data in other, uncommitted transactions */ unsigned int conntimeout; /*!< Maximum time the connection process should take */ + unsigned int maxconnections; /*!< Maximum number of allowed connections */ /*! When a connection fails, cache that failure for how long? */ struct timeval negative_connection_cache; /*! When a connection fails, when did that last occur? */ struct timeval last_negative_connect; + /*! A pool of available connections */ + AST_LIST_HEAD_NOLOCK(, odbc_obj) connections; + /*! Lock to protect the connections */ + ast_mutex_t lock; + /*! Condition to notify any pending connection requesters */ + ast_cond_t cond; + /*! The total number of current connections */ + size_t connection_cnt; }; static struct ao2_container *class_container; @@ -90,7 +99,7 @@ static AST_RWLIST_HEAD_STATIC(odbc_tables, odbc_cache_tables); static odbc_status odbc_obj_connect(struct odbc_obj *obj); static odbc_status odbc_obj_disconnect(struct odbc_obj *obj); -static int odbc_register_class(struct odbc_class *class, int connect); +static void odbc_register_class(struct odbc_class *class, int connect); AST_THREADSTORAGE(errors_buf); @@ -157,6 +166,8 @@ int ast_odbc_text2isolation(const char *txt) static void odbc_class_destructor(void *data) { struct odbc_class *class = data; + struct odbc_obj *obj; + /* Due to refcounts, we can safely assume that any objects with a reference * to us will prevent our destruction, so we don't need to worry about them. */ @@ -169,7 +180,14 @@ static void odbc_class_destructor(void *data) if (class->sanitysql) { ast_free(class->sanitysql); } + + while ((obj = AST_LIST_REMOVE_HEAD(&class->connections, list))) { + ao2_ref(obj, -1); + } + SQLFreeHandle(SQL_HANDLE_ENV, class->env); + ast_mutex_destroy(&class->lock); + ast_cond_destroy(&class->cond); } static int null_hash_fn(const void *obj, const int flags) @@ -180,21 +198,23 @@ static int null_hash_fn(const void *obj, const int flags) static void odbc_obj_destructor(void *data) { struct odbc_obj *obj = data; - struct odbc_class *class = obj->parent; - obj->parent = NULL; + odbc_obj_disconnect(obj); - ao2_ref(class, -1); } -static void destroy_table_cache(struct odbc_cache_tables *table) { +static void destroy_table_cache(struct odbc_cache_tables *table) +{ struct odbc_cache_columns *col; + ast_debug(1, "Destroying table cache for %s\n", table->table); + AST_RWLIST_WRLOCK(&table->columns); while ((col = AST_RWLIST_REMOVE_HEAD(&table->columns, list))) { ast_free(col); } AST_RWLIST_UNLOCK(&table->columns); AST_RWLIST_HEAD_DESTROY(&table->columns); + ast_free(table); } @@ -370,18 +390,19 @@ SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_c * We must therefore redo everything when we establish a new * connection. */ stmt = prepare_cb(obj, data); + if (!stmt) { + return NULL; + } - if (stmt) { - res = SQLExecute(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { - if (res == SQL_ERROR) { - ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute"); - } - - ast_log(LOG_WARNING, "SQL Execute error %d!\n", res); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - stmt = NULL; + res = SQLExecute(stmt); + if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) { + if (res == SQL_ERROR) { + ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute"); } + + ast_log(LOG_WARNING, "SQL Execute error %d!\n", res); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; } return stmt; @@ -468,7 +489,7 @@ static int load_odbc_config(void) struct ast_variable *v; char *cat; const char *dsn, *username, *password, *sanitysql; - int enabled, bse, conntimeout, forcecommit, isolation; + int enabled, bse, conntimeout, forcecommit, isolation, maxconnections; struct timeval ncache = { 0, 0 }; int preconnect = 0, res = 0; struct ast_flags config_flags = { 0 }; @@ -495,6 +516,7 @@ static int load_odbc_config(void) conntimeout = 10; forcecommit = 0; isolation = SQL_TXN_READ_COMMITTED; + maxconnections = 1; for (v = ast_variable_browse(config, cat); v; v = v->next) { if (!strcasecmp(v->name, "pooling") || !strncasecmp(v->name, "share", 5) || @@ -538,6 +560,11 @@ static int load_odbc_config(void) ast_log(LOG_ERROR, "Unrecognized value for 'isolation': '%s' in section '%s'\n", v->value, cat); isolation = SQL_TXN_READ_COMMITTED; } + } else if (!strcasecmp(v->name, "max_connections")) { + if (sscanf(v->value, "%30d", &maxconnections) != 1 || maxconnections < 1) { + ast_log(LOG_WARNING, "max_connections must be a positive integer\n"); + maxconnections = 1; + } } } @@ -563,6 +590,7 @@ static int load_odbc_config(void) new->isolation = isolation; new->conntimeout = conntimeout; new->negative_connection_cache = ncache; + new->maxconnections = maxconnections; if (cat) ast_copy_string(new->name, cat, sizeof(new->name)); @@ -581,6 +609,9 @@ static int load_odbc_config(void) break; } + ast_mutex_init(&new->lock); + ast_cond_init(&new->cond, NULL); + odbc_register_class(new, preconnect); ast_log(LOG_NOTICE, "Registered ODBC class '%s' dsn->[%s]\n", cat, dsn); ao2_ref(new, -1); @@ -641,6 +672,7 @@ static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_c ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %T", &tm); ast_cli(a->fd, " Name: %s\n DSN: %s\n", class->name, class->dsn); ast_cli(a->fd, " Last connection attempt: %s\n", timestr); + ast_cli(a->fd, " Number of active connections: %zd (out of %d)\n", class->connection_cnt, class->maxconnections); ast_cli(a->fd, "\n"); } ao2_ref(class, -1); @@ -654,38 +686,47 @@ static struct ast_cli_entry cli_odbc[] = { AST_CLI_DEFINE(handle_cli_odbc_show, "List ODBC DSN(s)") }; -static int odbc_register_class(struct odbc_class *class, int preconnect) +static void odbc_register_class(struct odbc_class *class, int preconnect) { struct odbc_obj *obj; - if (class) { - ao2_link(class_container, class); - /* I still have a reference in the caller, so a deref is NOT missing here. */ - - if (preconnect) { - /* Request and release builds a connection */ - obj = ast_odbc_request_obj(class->name, 0); - if (obj) { - ast_odbc_release_obj(obj); - } - } - return 0; - } else { - ast_log(LOG_WARNING, "Attempted to register a NULL class?\n"); - return -1; + ao2_link(class_container, class); + /* I still have a reference in the caller, so a deref is NOT missing here. */ + + if (!preconnect) { + return; } + + /* Request and release builds a connection */ + obj = ast_odbc_request_obj(class->name, 0); + if (obj) { + ast_odbc_release_obj(obj); + } + + return; } void ast_odbc_release_obj(struct odbc_obj *obj) { - ast_debug(2, "Releasing ODBC handle %p\n", obj); + struct odbc_class *class = obj->parent; -#ifdef DEBUG_THREADS - obj->file[0] = '\0'; - obj->function[0] = '\0'; - obj->lineno = 0; -#endif - ao2_ref(obj, -1); + ast_debug(2, "Releasing ODBC handle %p into pool\n", obj); + + /* The odbc_obj only holds a reference to the class when it is + * actively being used. This guarantees no circular reference + * between odbc_class and odbc_obj. Since it is being released + * we also release our class reference. If a reload occurred before + * the class will go away automatically once all odbc_obj are + * released back. + */ + obj->parent = NULL; + + ast_mutex_lock(&class->lock); + AST_LIST_INSERT_HEAD(&class->connections, obj, list); + ast_cond_signal(&class->cond); + ast_mutex_unlock(&class->lock); + + ao2_ref(class, -1); } int ast_odbc_backslash_is_escape(struct odbc_obj *obj) @@ -703,6 +744,50 @@ static int aoro2_class_cb(void *obj, void *arg, int flags) return 0; } +/* + * \brief Determine if the connection has died. + * + * \param connection The connection to check + * \param class The ODBC class + * \retval 1 Yep, it's dead + * \retval 0 It's alive and well + */ +static int connection_dead(struct odbc_obj *connection, struct odbc_class *class) +{ + char *test_sql = "select 1"; + SQLINTEGER dead; + SQLRETURN res; + SQLHSTMT stmt; + + res = SQLGetConnectAttr(connection->con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0); + if (SQL_SUCCEEDED(res)) { + return dead == SQL_CD_TRUE ? 1 : 0; + } + + /* If the Driver doesn't support SQL_ATTR_CONNECTION_DEAD do a + * probing query instead + */ + res = SQLAllocHandle(SQL_HANDLE_STMT, connection->con, &stmt); + if (!SQL_SUCCEEDED(res)) { + return 1; + } + + if (!ast_strlen_zero(class->sanitysql)) { + test_sql = class->sanitysql; + } + + res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS); + if (!SQL_SUCCEEDED(res)) { + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + return 1; + } + + res = SQLExecute(stmt); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + return SQL_SUCCEEDED(res) ? 0 : 1; +} + struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags, const char *file, const char *function, int lineno) { struct odbc_obj *obj = NULL; @@ -713,17 +798,60 @@ struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags return NULL; } - /* XXX ODBC connection objects do not have shared ownership, so there is no reason - * to use refcounted objects here. - */ - obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor); - /* Inherit reference from the ao2_callback from before */ - obj->parent = class; - if (odbc_obj_connect(obj) == ODBC_FAIL) { - ao2_ref(obj, -1); - return NULL; + ast_mutex_lock(&class->lock); + + while (!obj) { + obj = AST_LIST_REMOVE_HEAD(&class->connections, list); + + if (!obj) { + if (class->connection_cnt < class->maxconnections) { + /* If no connection is immediately available establish a new + * one if allowed. If we try and fail we give up completely as + * we could go into an infinite loop otherwise. + */ + obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor); + if (!obj) { + break; + } + + obj->parent = ao2_bump(class); + if (odbc_obj_connect(obj) == ODBC_FAIL) { + ao2_ref(obj->parent, -1); + ao2_ref(obj, -1); + obj = NULL; + break; + } + + class->connection_cnt++; + ast_debug(2, "Created ODBC handle %p on class '%s', new count is %zd\n", obj, + name, class->connection_cnt); + } else { + /* Otherwise if we're not allowed to create a new one we + * wait for another thread to give up the connection they + * own. + */ + ast_cond_wait(&class->cond, &class->lock); + } + } else if (connection_dead(obj, class)) { + /* If the connection is dead try to grab another functional one from the + * pool instead of trying to resurrect this one. + */ + ao2_ref(obj, -1); + obj = NULL; + class->connection_cnt--; + ast_debug(2, "ODBC handle %p dead - removing from class '%s', new count is %zd\n", + obj, name, class->connection_cnt); + } else { + /* We successfully grabbed a connection from the pool and all is well! + */ + obj->parent = ao2_bump(class); + ast_debug(2, "Reusing ODBC handle %p from class '%s'\n", obj, name); + } } + ast_mutex_unlock(&class->lock); + ao2_ref(class, -1); + return obj; } @@ -755,14 +883,6 @@ static odbc_status odbc_obj_disconnect(struct odbc_obj *obj) obj->con = NULL; res = SQLDisconnect(con); - if (obj->parent) { - if (res == SQL_SUCCESS || res == SQL_SUCCESS_WITH_INFO) { - ast_debug(3, "Disconnected %d from %s [%s](%p)\n", res, obj->parent->name, obj->parent->dsn, obj); - } else { - ast_debug(3, "res_odbc: %s [%s](%p) already disconnected\n", obj->parent->name, obj->parent->dsn, obj); - } - } - if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) == SQL_SUCCESS) { ast_debug(3, "Database handle %p (connection %p) deallocated\n", obj, con); } else { diff --git a/res/res_pjsip/pjsip_distributor.c b/res/res_pjsip/pjsip_distributor.c index 0d3df06f0..3867eaea0 100644 --- a/res/res_pjsip/pjsip_distributor.c +++ b/res/res_pjsip/pjsip_distributor.c @@ -297,13 +297,13 @@ static pj_bool_t distributor(pjsip_rx_data *rdata) if (dlg) { ast_debug(3, "Searching for serializer on dialog %s for %s\n", - dlg->obj_name, rdata->msg_info.info); + dlg->obj_name, pjsip_rx_data_get_info(rdata)); dist = pjsip_dlg_get_mod_data(dlg, distributor_mod.id); if (dist) { serializer = ao2_bump(dist->serializer); if (serializer) { ast_debug(3, "Found serializer %s on dialog %s\n", - ast_taskprocessor_name(serializer), dlg->obj_name); + ast_taskprocessor_name(serializer), dlg->obj_name); } } pjsip_dlg_dec_lock(dlg); @@ -313,7 +313,7 @@ static pj_bool_t distributor(pjsip_rx_data *rdata) /* We have a serializer so we know where to send the message. */ } else if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) { ast_debug(3, "No dialog serializer for response %s. Using request transaction as basis\n", - rdata->msg_info.info); + pjsip_rx_data_get_info(rdata)); serializer = find_request_serializer(rdata); } else if (!pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_cancel_method) || !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_bye_method)) { diff --git a/res/res_pjsip_mwi_body_generator.c b/res/res_pjsip_mwi_body_generator.c index f6aca2df1..54b078212 100644 --- a/res/res_pjsip_mwi_body_generator.c +++ b/res/res_pjsip_mwi_body_generator.c @@ -61,11 +61,11 @@ static int mwi_generate_body_content(void *body, void *data) ast_str_append(mwi, 0, "Messages-Waiting: %s\r\n", counter->new_msgs ? "yes" : "no"); - ast_str_append(mwi, 0, "Voice-Message: %d/%d (0/0)\r\n", - counter->new_msgs, counter->old_msgs); if (!ast_strlen_zero(counter->message_account)) { ast_str_append(mwi, 0, "Message-Account: %s\r\n", counter->message_account); } + ast_str_append(mwi, 0, "Voice-Message: %d/%d (0/0)\r\n", + counter->new_msgs, counter->old_msgs); return 0; } diff --git a/res/res_srtp.c b/res/res_srtp.c index 8d8daf0b0..97773c125 100644 --- a/res/res_srtp.c +++ b/res/res_srtp.c @@ -40,7 +40,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include <srtp/srtp.h> +#ifdef HAVE_OPENSSL +#include <openssl/rand.h> +#else #include <srtp/crypto_kernel.h> +#endif #include "asterisk/lock.h" #include "asterisk/sched.h" @@ -305,7 +309,11 @@ static int ast_srtp_policy_set_master_key(struct ast_srtp_policy *policy, const static int ast_srtp_get_random(unsigned char *key, size_t len) { +#ifdef HAVE_OPENSSL + return RAND_bytes(key, len) > 0 ? 0: -1; +#else return crypto_get_random(key, len) != err_status_ok ? -1: 0; +#endif } static void ast_srtp_set_cb(struct ast_srtp *srtp, const struct ast_srtp_cb *cb, void *data) diff --git a/third-party/pjproject/patches/0001-2.4.5-fix-for-tls-async-ops.patch b/third-party/pjproject/patches/0001-2.4.5-fix-for-tls-async-ops.patch deleted file mode 100644 index 33fc8ea4e..000000000 --- a/third-party/pjproject/patches/0001-2.4.5-fix-for-tls-async-ops.patch +++ /dev/null @@ -1,224 +0,0 @@ -diff --git a/pjlib/include/pj/ssl_sock.h b/pjlib/include/pj/ssl_sock.h -index 1682bda..a69af32 100644 ---- a/pjlib/include/pj/ssl_sock.h -+++ b/pjlib/include/pj/ssl_sock.h -@@ -864,6 +864,18 @@ PJ_DECL(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param); - - - /** -+ * Duplicate pj_ssl_sock_param. -+ * -+ * @param pool Pool to allocate memory. -+ * @param dst Destination parameter. -+ * @param src Source parameter. -+ */ -+PJ_DECL(void) pj_ssl_sock_param_copy(pj_pool_t *pool, -+ pj_ssl_sock_param *dst, -+ const pj_ssl_sock_param *src); -+ -+ -+/** - * Create secure socket instance. - * - * @param pool The pool for allocating secure socket instance. -@@ -1115,6 +1127,30 @@ PJ_DECL(pj_status_t) pj_ssl_sock_start_accept(pj_ssl_sock_t *ssock, - - - /** -+ * Same as #pj_ssl_sock_start_accept(), but application can provide -+ * a secure socket parameter, which will be used to create a new secure -+ * socket reported in \a on_accept_complete() callback when there is -+ * an incoming connection. -+ * -+ * @param ssock The secure socket. -+ * @param pool Pool used to allocate some internal data for the -+ * operation. -+ * @param localaddr Local address to bind on. -+ * @param addr_len Length of buffer containing local address. -+ * @param newsock_param Secure socket parameter for new accepted sockets. -+ * -+ * @return PJ_SUCCESS if the operation has been successful, -+ * or the appropriate error code on failure. -+ */ -+PJ_DECL(pj_status_t) -+pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock, -+ pj_pool_t *pool, -+ const pj_sockaddr_t *local_addr, -+ int addr_len, -+ const pj_ssl_sock_param *newsock_param); -+ -+ -+/** - * Starts asynchronous socket connect() operation and SSL/TLS handshaking - * for this socket. Once the connection is done (either successfully or not), - * the \a on_connect_complete() callback will be called. -diff --git a/pjlib/src/pj/ssl_sock_common.c b/pjlib/src/pj/ssl_sock_common.c -index 913efee..717ab1d 100644 ---- a/pjlib/src/pj/ssl_sock_common.c -+++ b/pjlib/src/pj/ssl_sock_common.c -@@ -19,6 +19,7 @@ - #include <pj/ssl_sock.h> - #include <pj/assert.h> - #include <pj/errno.h> -+#include <pj/pool.h> - #include <pj/string.h> - - /* -@@ -48,6 +49,31 @@ PJ_DEF(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param) - } - - -+/* -+ * Duplicate SSL socket parameter. -+ */ -+PJ_DEF(void) pj_ssl_sock_param_copy( pj_pool_t *pool, -+ pj_ssl_sock_param *dst, -+ const pj_ssl_sock_param *src) -+{ -+ /* Init secure socket param */ -+ pj_memcpy(dst, src, sizeof(*dst)); -+ if (src->ciphers_num > 0) { -+ unsigned i; -+ dst->ciphers = (pj_ssl_cipher*) -+ pj_pool_calloc(pool, src->ciphers_num, -+ sizeof(pj_ssl_cipher)); -+ for (i = 0; i < src->ciphers_num; ++i) -+ dst->ciphers[i] = src->ciphers[i]; -+ } -+ -+ if (src->server_name.slen) { -+ /* Server name must be null-terminated */ -+ pj_strdup_with_null(pool, &dst->server_name, &src->server_name); -+ } -+} -+ -+ - PJ_DEF(pj_status_t) pj_ssl_cert_get_verify_status_strings( - pj_uint32_t verify_status, - const char *error_strings[], -diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c -index 40a5a1e..6a701b7 100644 ---- a/pjlib/src/pj/ssl_sock_ossl.c -+++ b/pjlib/src/pj/ssl_sock_ossl.c -@@ -141,6 +141,7 @@ struct pj_ssl_sock_t - pj_pool_t *pool; - pj_ssl_sock_t *parent; - pj_ssl_sock_param param; -+ pj_ssl_sock_param newsock_param; - pj_ssl_cert_t *cert; - - pj_ssl_cert_info local_cert_info; -@@ -1757,11 +1758,9 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, - unsigned i; - pj_status_t status; - -- PJ_UNUSED_ARG(src_addr_len); -- - /* Create new SSL socket instance */ -- status = pj_ssl_sock_create(ssock_parent->pool, &ssock_parent->param, -- &ssock); -+ status = pj_ssl_sock_create(ssock_parent->pool, -+ &ssock_parent->newsock_param, &ssock); - if (status != PJ_SUCCESS) - goto on_return; - -@@ -2183,20 +2182,8 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool, - return status; - - /* Init secure socket param */ -- ssock->param = *param; -+ pj_ssl_sock_param_copy(pool, &ssock->param, param); - ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3; -- if (param->ciphers_num > 0) { -- unsigned i; -- ssock->param.ciphers = (pj_ssl_cipher*) -- pj_pool_calloc(pool, param->ciphers_num, -- sizeof(pj_ssl_cipher)); -- for (i = 0; i < param->ciphers_num; ++i) -- ssock->param.ciphers[i] = param->ciphers[i]; -- } -- -- /* Server name must be null-terminated */ -- pj_strdup_with_null(pool, &ssock->param.server_name, -- ¶m->server_name); - - /* Finally */ - *p_ssock = ssock; -@@ -2617,12 +2604,36 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock, - const pj_sockaddr_t *localaddr, - int addr_len) - { -+ return pj_ssl_sock_start_accept2(ssock, pool, localaddr, addr_len, -+ &ssock->param); -+} -+ -+ -+/** -+ * Same as #pj_ssl_sock_start_accept(), but application provides parameter -+ * for new accepted secure sockets. -+ */ -+PJ_DEF(pj_status_t) -+pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock, -+ pj_pool_t *pool, -+ const pj_sockaddr_t *localaddr, -+ int addr_len, -+ const pj_ssl_sock_param *newsock_param) -+{ - pj_activesock_cb asock_cb; - pj_activesock_cfg asock_cfg; - pj_status_t status; - - PJ_ASSERT_RETURN(ssock && pool && localaddr && addr_len, PJ_EINVAL); - -+ /* Verify new socket parameters */ -+ if (newsock_param->grp_lock != ssock->param.grp_lock || -+ newsock_param->sock_af != ssock->param.sock_af || -+ newsock_param->sock_type != ssock->param.sock_type) -+ { -+ return PJ_EINVAL; -+ } -+ - /* Create socket */ - status = pj_sock_socket(ssock->param.sock_af, ssock->param.sock_type, 0, - &ssock->sock); -@@ -2691,6 +2702,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock, - goto on_error; - - /* Start accepting */ -+ pj_ssl_sock_param_copy(pool, &ssock->newsock_param, newsock_param); - status = pj_activesock_start_accept(ssock->asock, pool); - if (status != PJ_SUCCESS) - goto on_error; -diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c -index a9e95fb..91d99a7 100644 ---- a/pjsip/src/pjsip/sip_transport_tls.c -+++ b/pjsip/src/pjsip/sip_transport_tls.c -@@ -314,7 +314,7 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt, - int af, sip_ssl_method; - pj_uint32_t sip_ssl_proto; - struct tls_listener *listener; -- pj_ssl_sock_param ssock_param; -+ pj_ssl_sock_param ssock_param, newsock_param; - pj_sockaddr *listener_addr; - pj_bool_t has_listener; - pj_status_t status; -@@ -473,9 +473,14 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt, - */ - has_listener = PJ_FALSE; - -- status = pj_ssl_sock_start_accept(listener->ssock, pool, -+ pj_memcpy(&newsock_param, &ssock_param, sizeof(newsock_param)); -+ newsock_param.async_cnt = 1; -+ newsock_param.cb.on_data_read = &on_data_read; -+ newsock_param.cb.on_data_sent = &on_data_sent; -+ status = pj_ssl_sock_start_accept2(listener->ssock, pool, - (pj_sockaddr_t*)listener_addr, -- pj_sockaddr_get_len((pj_sockaddr_t*)listener_addr)); -+ pj_sockaddr_get_len((pj_sockaddr_t*)listener_addr), -+ &newsock_param); - if (status == PJ_SUCCESS || status == PJ_EPENDING) { - pj_ssl_sock_info info; - has_listener = PJ_TRUE; --- -cgit v0.11.2 - diff --git a/third-party/pjproject/patches/0001-Bump-tcp-tls-and-transaction-log-levels-from-1-to-3.patch b/third-party/pjproject/patches/0001-Bump-tcp-tls-and-transaction-log-levels-from-1-to-3.patch deleted file mode 100644 index 9873abf0e..000000000 --- a/third-party/pjproject/patches/0001-Bump-tcp-tls-and-transaction-log-levels-from-1-to-3.patch +++ /dev/null @@ -1,70 +0,0 @@ -From a147b72df1ec150c1d733e882225db86142fb339 Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Sun, 21 Feb 2016 10:01:53 -0700 -Subject: [PATCH] Bump tcp/tls and transaction log levels from 1 to 3 - -sip_transport_tcp, sip_transport_tls and sip_transaction are printing messages -at log level 1 or 2 for things that are transient, recoverable, possibly -expected, or are handled with return codes. A good example of this is if we're -trying to send an OPTIONS message to a TCP client that has disappeared. Both -sip_transport_tcp and sip_transaction are printing "connection refused" -messages because the remote client isn't listening. This is generally expected -behavior and it should be up to the app caller to determine if an error message -is warranted. ---- - pjsip/src/pjsip/sip_transaction.c | 4 ++-- - pjsip/src/pjsip/sip_transport_tcp.c | 2 +- - pjsip/src/pjsip/sip_transport_tls.c | 2 +- - 3 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c -index 46bd971..1b4fdb7 100644 ---- a/pjsip/src/pjsip/sip_transaction.c -+++ b/pjsip/src/pjsip/sip_transaction.c -@@ -1898,7 +1898,7 @@ static void send_msg_callback( pjsip_send_state *send_state, - - err =pj_strerror((pj_status_t)-sent, errmsg, sizeof(errmsg)); - -- PJ_LOG(2,(tsx->obj_name, -+ PJ_LOG(3,(tsx->obj_name, - "Failed to send %s! err=%d (%s)", - pjsip_tx_data_get_info(send_state->tdata), -sent, - errmsg)); -@@ -1938,7 +1938,7 @@ static void send_msg_callback( pjsip_send_state *send_state, - } - - } else { -- PJ_PERROR(2,(tsx->obj_name, (pj_status_t)-sent, -+ PJ_PERROR(3,(tsx->obj_name, (pj_status_t)-sent, - "Temporary failure in sending %s, " - "will try next server", - pjsip_tx_data_get_info(send_state->tdata))); -diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c -index 222cb13..1bbb324 100644 ---- a/pjsip/src/pjsip/sip_transport_tcp.c -+++ b/pjsip/src/pjsip/sip_transport_tcp.c -@@ -164,7 +164,7 @@ static void tcp_perror(const char *sender, const char *title, - - pj_strerror(status, errmsg, sizeof(errmsg)); - -- PJ_LOG(1,(sender, "%s: %s [code=%d]", title, errmsg, status)); -+ PJ_LOG(3,(sender, "%s: %s [code=%d]", title, errmsg, status)); - } - - -diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c -index 617d7f5..a83ac32 100644 ---- a/pjsip/src/pjsip/sip_transport_tls.c -+++ b/pjsip/src/pjsip/sip_transport_tls.c -@@ -170,7 +170,7 @@ static void tls_perror(const char *sender, const char *title, - - pj_strerror(status, errmsg, sizeof(errmsg)); - -- PJ_LOG(1,(sender, "%s: %s [code=%d]", title, errmsg, status)); -+ PJ_LOG(3,(sender, "%s: %s [code=%d]", title, errmsg, status)); - } - - --- -2.5.0 - diff --git a/third-party/pjproject/patches/0001-ioqueue-Enable-epoll-in-aconfigure.ac.patch b/third-party/pjproject/patches/0001-ioqueue-Enable-epoll-in-aconfigure.ac.patch deleted file mode 100644 index 36b6c651f..000000000 --- a/third-party/pjproject/patches/0001-ioqueue-Enable-epoll-in-aconfigure.ac.patch +++ /dev/null @@ -1,80 +0,0 @@ -From b5c0bc905911f75e08987e6833075481fe16dab2 Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Mon, 22 Feb 2016 13:05:59 -0700 -Subject: [PATCH] ioqueue: Enable epoll in aconfigure.ac - -Although the --enable-epoll option was being accepted, the result -was always forced to select. This patch updates aconfigure.ac -to properly set the value of ac_linux_poll if --enable-epoll is -specified. ---- - README.txt | 1 + - aconfigure | 11 +++++++---- - aconfigure.ac | 7 +++++-- - pjlib/include/pj/compat/os_auto.h.in | 3 +++ - 4 files changed, 16 insertions(+), 6 deletions(-) - -diff --git a/README.txt b/README.txt -index bc45da8..48415fd 100644 ---- a/README.txt -+++ b/README.txt -@@ -463,6 +463,7 @@ Using Default Settings - $ ./configure --help - ... - Optional Features: -+ --enable-epoll Use epoll on Linux instead of select - --disable-floating-point Disable floating point where possible - --disable-sound Exclude sound (i.e. use null sound) - --disable-small-filter Exclude small filter in resampling -diff --git a/aconfigure.ac b/aconfigure.ac -index 2f71abb..3e88124 100644 ---- a/aconfigure.ac -+++ b/aconfigure.ac -@@ -410,6 +410,7 @@ dnl ###################### - dnl # ioqueue selection - dnl # - AC_SUBST(ac_os_objs) -+AC_SUBST(ac_linux_poll) - AC_MSG_CHECKING([ioqueue backend]) - AC_ARG_ENABLE(epoll, - AC_HELP_STRING([--enable-epoll], -@@ -417,10 +418,13 @@ AC_ARG_ENABLE(epoll, - [ - ac_os_objs=ioqueue_epoll.o - AC_MSG_RESULT([/dev/epoll]) -+ AC_DEFINE(PJ_HAS_LINUX_EPOLL,1) -+ ac_linux_poll=epoll - ], - [ - ac_os_objs=ioqueue_select.o -- AC_MSG_RESULT([select()]) -+ AC_MSG_RESULT([select()]) -+ ac_linux_poll=select - ]) - - AC_SUBST(ac_shared_libraries) -@@ -1879,7 +1883,6 @@ esac - - - AC_SUBST(target) --AC_SUBST(ac_linux_poll,select) - AC_SUBST(ac_host,unix) - AC_SUBST(ac_main_obj) - case $target in -diff --git a/pjlib/include/pj/compat/os_auto.h.in b/pjlib/include/pj/compat/os_auto.h.in -index 77980d3..c8e73b2 100644 ---- a/pjlib/include/pj/compat/os_auto.h.in -+++ b/pjlib/include/pj/compat/os_auto.h.in -@@ -128,6 +128,9 @@ - */ - #undef PJ_SELECT_NEEDS_NFDS - -+/* Was Linux epoll support enabled */ -+#undef PJ_HAS_LINUX_EPOLL -+ - /* Is errno a good way to retrieve OS errors? - */ - #undef PJ_HAS_ERRNO_VAR --- -2.5.0 - diff --git a/third-party/pjproject/patches/0001-pjsip-apps-src-python-setup.py-Take-make-from-the-en.patch b/third-party/pjproject/patches/0001-pjsip-apps-src-python-setup.py-Take-make-from-the-en.patch deleted file mode 100644 index 80f8bc0b3..000000000 --- a/third-party/pjproject/patches/0001-pjsip-apps-src-python-setup.py-Take-make-from-the-en.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 61668b8fcaa0f2a8a05100097284c0c427600033 Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Mon, 2 May 2016 17:08:15 -0600 -Subject: [PATCH] pjsip-apps/src/python/setup.py: Take "make" from the - environment - -With "make" hard coded in setup.py, it chokes on FreeBSD because the system -make command isn't GNU compatibile. This patch allows setup.py to take the -name of the make command from the MAKE environment variable if it exists. -If it doesn't, it defaults to "make". ---- - pjsip-apps/src/python/setup.py | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/pjsip-apps/src/python/setup.py b/pjsip-apps/src/python/setup.py -index 69a9859..ea1427d 100644 ---- a/pjsip-apps/src/python/setup.py -+++ b/pjsip-apps/src/python/setup.py -@@ -60,25 +60,25 @@ if pj_version_suffix: - pj_version += "-" + pj_version_suffix - - #print 'PJ_VERSION = "'+ pj_version + '"' -- -+MAKE = os.environ.get('MAKE') or "make" - - # Fill in pj_inc_dirs - pj_inc_dirs = [] --f = os.popen("make -f helper.mak inc_dir") -+f = os.popen("%s -f helper.mak inc_dir" % MAKE) - for line in f: - pj_inc_dirs.append(line.rstrip("\r\n")) - f.close() - - # Fill in pj_lib_dirs - pj_lib_dirs = [] --f = os.popen("make -f helper.mak lib_dir") -+f = os.popen("%s -f helper.mak lib_dir" % MAKE) - for line in f: - pj_lib_dirs.append(line.rstrip("\r\n")) - f.close() - - # Fill in pj_libs - pj_libs = [] --f = os.popen("make -f helper.mak libs") -+f = os.popen("%s -f helper.mak libs" % MAKE) - for line in f: - pj_libs.append(line.rstrip("\r\n")) - f.close() --- -2.5.5 - diff --git a/third-party/pjproject/patches/0001-sip_parser.c-Fix-pjsip_VIA_PARAM_SPEC_ESC.patch b/third-party/pjproject/patches/0001-sip_parser.c-Fix-pjsip_VIA_PARAM_SPEC_ESC.patch deleted file mode 100644 index 60c27cb1a..000000000 --- a/third-party/pjproject/patches/0001-sip_parser.c-Fix-pjsip_VIA_PARAM_SPEC_ESC.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0fc7ef5f01be9cc74d184c3ca3a973ff1ef44c93 Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Sun, 10 Apr 2016 12:54:06 -0600 -Subject: [PATCH] sip_parser.c: Fix pjsip_VIA_PARAM_SPEC_ESC - -pjsip_VIA_PARAM_SPEC_ESC should have been pjsip_TOKEN_SPEC_ESC + ":" but -instead of appending ":" to pjsip_VIA_PARAM_SPEC_ESC it was being appended -to pjsip_VIA_PARAM_SPEC again. This was causing parsing of Via headers -to fail when an ipv6 address was in a "received" param and -PJSIP_UNESCAPE_IN_PLACE was used. Probably just a copy/paste error. ---- - pjsip/src/pjsip/sip_parser.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c -index 378c22f..c18faa3 100644 ---- a/pjsip/src/pjsip/sip_parser.c -+++ b/pjsip/src/pjsip/sip_parser.c -@@ -327,7 +327,7 @@ static pj_status_t init_parser() - - status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC); - PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); -- pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":"); -+ pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC_ESC, ":"); - - status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC); - PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); --- -2.5.5 - diff --git a/third-party/pjproject/patches/0001-sip_parser.c-Remove-wholesale-strip-from-parse_param.patch b/third-party/pjproject/patches/0001-sip_parser.c-Remove-wholesale-strip-from-parse_param.patch deleted file mode 100644 index e0bd9129c..000000000 --- a/third-party/pjproject/patches/0001-sip_parser.c-Remove-wholesale-strip-from-parse_param.patch +++ /dev/null @@ -1,55 +0,0 @@ -From ce426249ec1270f27560919791f3e13eaeea9152 Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Tue, 12 Apr 2016 14:09:53 -0600 -Subject: [PATCH] sip_parser.c: Remove wholesale '[]' strip from - parse_param_impl - -The wholesale stripping of '[]' from header parameters causes issues if -something (like a port) occurrs after the final ']'. - -'[2001:a::b]' will correctly parse to '2001:a::b' -'[2001:a::b]:8080' will correctly parse to '2001:a::b' but the scanner is left -with ':8080' and parsing stops with a syntax error. - -I can't even find a case where stripping the '[]' is a good thing anyway. Even -if you continued to parse and resulted in a string that looks like this... -'2001:a::b:8080', it's not valid. - -This came up in Asterisk because Kamailio sends us a Contact with an alias -URI parameter that has an IPv6 address in it like this: -Contact: <sip:1171@127.0.0.1:5080;alias=[2001:1:2::3]~43691~6> -which should be legal but causes a syntax error because of the characters -after the final ']'. Even if it didn't, the '[]' should still not be stripped. - -I've run the Asterisk Test Suite for PJSIP (252 tests) many of which are IPv6 -enabled. No issues were caused by removing the code that strips the '[]'. - -I tried running 'make pjsip-test' but that fails even without my change. :) - -The Asterisk ticket is: https://issues.asterisk.org/jira/browse/ASTERISK-25123 ---- - pjsip/src/pjsip/sip_parser.c | 8 -------- - 1 file changed, 8 deletions(-) - -diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c -index c18faa3..98eb5ea 100644 ---- a/pjsip/src/pjsip/sip_parser.c -+++ b/pjsip/src/pjsip/sip_parser.c -@@ -1149,14 +1149,6 @@ static void parse_param_imp( pj_scanner *scanner, pj_pool_t *pool, - pvalue->ptr++; - pvalue->slen -= 2; - } -- } else if (*scanner->curptr == '[') { -- /* pvalue can be a quoted IPv6; in this case, the -- * '[' and ']' quote characters are to be removed -- * from the pvalue. -- */ -- pj_scan_get_char(scanner); -- pj_scan_get_until_ch(scanner, ']', pvalue); -- pj_scan_get_char(scanner); - } else if(pj_cis_match(spec, *scanner->curptr)) { - parser_get_and_unescape(scanner, pool, spec, esc_spec, pvalue); - } --- -2.5.5 - diff --git a/third-party/pjproject/patches/0001-sip_transport-Search-for-transport-even-if-listener-.patch b/third-party/pjproject/patches/0001-sip_transport-Search-for-transport-even-if-listener-.patch deleted file mode 100644 index 001912cfe..000000000 --- a/third-party/pjproject/patches/0001-sip_transport-Search-for-transport-even-if-listener-.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 552194179eb6deae8326eb0fef446e69240ea41b Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Fri, 19 Feb 2016 17:05:53 -0700 -Subject: [PATCH] sip_transport: Search for transport even if listener was - specified. - -If a listener was specified when calling pjsip_tpmgr_acquire_transport2, -a new transport was always created instead of using an existing one. This -caused several issues mostly related to the remote end not expecting a new -connection. I.E. A TCP client who registered to a server is not going to -be listening for connections coming back from the server and refuses the -connection. - -Now when pjsip_tpmgr_acquire_transport2 is called with a listener, the -registry is still searched for an existing transport and the listener -is used as a factory only if no existing transport can be found. ---- - pjsip/src/pjsip/sip_transport.c | 68 ++++++++++++++++++++--------------------- - 1 file changed, 34 insertions(+), 34 deletions(-) - -diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c -index 0410324..620b9c0 100644 ---- a/pjsip/src/pjsip/sip_transport.c -+++ b/pjsip/src/pjsip/sip_transport.c -@@ -1999,29 +1999,11 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, - - TRACE_((THIS_FILE, "Transport %s acquired", seltp->obj_name)); - return PJ_SUCCESS; -- -- -- } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && -- sel->u.listener) -- { -- /* Application has requested that a specific listener is to -- * be used. In this case, skip transport hash table lookup. -- */ -- -- /* Verify that the listener type matches the destination type */ -- if (sel->u.listener->type != type) { -- pj_lock_release(mgr->lock); -- return PJSIP_ETPNOTSUITABLE; -- } -- -- /* We'll use this listener to create transport */ -- factory = sel->u.listener; -- - } else { - - /* - * This is the "normal" flow, where application doesn't specify -- * specific transport/listener to be used to send message to. -+ * specific transport to be used to send message to. - * In this case, lookup the transport from the hash table. - */ - pjsip_transport_key key; -@@ -2081,22 +2063,40 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr, - return PJ_SUCCESS; - } - -- /* -- * Transport not found! -- * Find factory that can create such transport. -- */ -- factory = mgr->factory_list.next; -- while (factory != &mgr->factory_list) { -- if (factory->type == type) -- break; -- factory = factory->next; -- } -+ if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && -+ sel->u.listener) -+ { -+ /* Application has requested that a specific listener is to -+ * be used. -+ */ -+ -+ /* Verify that the listener type matches the destination type */ -+ if (sel->u.listener->type != type) { -+ pj_lock_release(mgr->lock); -+ return PJSIP_ETPNOTSUITABLE; -+ } - -- if (factory == &mgr->factory_list) { -- /* No factory can create the transport! */ -- pj_lock_release(mgr->lock); -- TRACE_((THIS_FILE, "No suitable factory was found either")); -- return PJSIP_EUNSUPTRANSPORT; -+ /* We'll use this listener to create transport */ -+ factory = sel->u.listener; -+ -+ } else { -+ /* -+ * Transport not found! -+ * Find factory that can create such transport. -+ */ -+ factory = mgr->factory_list.next; -+ while (factory != &mgr->factory_list) { -+ if (factory->type == type) -+ break; -+ factory = factory->next; -+ } -+ -+ if (factory == &mgr->factory_list) { -+ /* No factory can create the transport! */ -+ pj_lock_release(mgr->lock); -+ TRACE_((THIS_FILE, "No suitable factory was found either")); -+ return PJSIP_EUNSUPTRANSPORT; -+ } - } - } - --- -2.5.0 - diff --git a/third-party/pjproject/patches/0001-sip_transport_tcp-tls-Set-factory-on-transports-crea.patch b/third-party/pjproject/patches/0001-sip_transport_tcp-tls-Set-factory-on-transports-crea.patch new file mode 100644 index 000000000..d8a9adbde --- /dev/null +++ b/third-party/pjproject/patches/0001-sip_transport_tcp-tls-Set-factory-on-transports-crea.patch @@ -0,0 +1,48 @@ +From b7cb93b0e1729589a71e8b30d9a9893f0918e2a2 Mon Sep 17 00:00:00 2001 +From: George Joseph <george.joseph@fairview5.com> +Date: Mon, 30 May 2016 11:58:22 -0600 +Subject: [PATCH] sip_transport_tcp/tls: Set factory on transports created + from accept + +The ability to re-use tcp and tls transports when a factory is +specified now depends on transport->factory being set which is a new field +in 2.5. This was being set only on new outgoing sockets not on +incoming sockets. The result was that a client REGISTER created a new +socket but without the factory set, the next outgoing request to the +client, OPTIONS, INVITE, etc, would attempt to create another socket +which the client would refuse. + +This patch sets the factory on transports created as a result of an +accept. +--- + pjsip/src/pjsip/sip_transport_tcp.c | 1 + + pjsip/src/pjsip/sip_transport_tls.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/pjsip/src/pjsip/sip_transport_tcp.c b/pjsip/src/pjsip/sip_transport_tcp.c +index 1bbb324..00eb8fc 100644 +--- a/pjsip/src/pjsip/sip_transport_tcp.c ++++ b/pjsip/src/pjsip/sip_transport_tcp.c +@@ -713,6 +713,7 @@ static pj_status_t tcp_create( struct tcp_listener *listener, + tcp->base.send_msg = &tcp_send_msg; + tcp->base.do_shutdown = &tcp_shutdown; + tcp->base.destroy = &tcp_destroy_transport; ++ tcp->base.factory = &listener->factory; + + /* Create group lock */ + status = pj_grp_lock_create(pool, NULL, &tcp->grp_lock); +diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c +index a83ac32..36ee70d 100644 +--- a/pjsip/src/pjsip/sip_transport_tls.c ++++ b/pjsip/src/pjsip/sip_transport_tls.c +@@ -742,6 +742,7 @@ static pj_status_t tls_create( struct tls_listener *listener, + tls->base.send_msg = &tls_send_msg; + tls->base.do_shutdown = &tls_shutdown; + tls->base.destroy = &tls_destroy_transport; ++ tls->base.factory = &listener->factory; + + tls->ssock = ssock; + +-- +2.5.5 + diff --git a/third-party/pjproject/patches/0002-aconfigure.ac-Fix-autoconf-issue-with-opencore-amrnb.patch b/third-party/pjproject/patches/0002-aconfigure.ac-Fix-autoconf-issue-with-opencore-amrnb.patch deleted file mode 100644 index 04d1d9703..000000000 --- a/third-party/pjproject/patches/0002-aconfigure.ac-Fix-autoconf-issue-with-opencore-amrnb.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 1281b60a1807d1285b101b6eb61c6478f29785fe Mon Sep 17 00:00:00 2001 -From: George Joseph <george.joseph@fairview5.com> -Date: Wed, 23 Mar 2016 07:48:52 -0600 -Subject: [PATCH] aconfigure.ac: Fix autoconf issue with opencore-amrnb on - older systems - -autoconf 2.63 on CentOS6 produces a bad ./aconfigure file related to -opencore-amrnb. - -./aconfigure: line 15158: syntax error near unexpected token `fi' - -To get around this, a 'true;' needed to be added to the Ok case of -AC_ARG_WITH(opencore-amrnb) ---- - aconfigure | 3 +++ - aconfigure.ac | 2 +- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/aconfigure b/aconfigure -index 33a08f5..4c122c2 100755 ---- a/aconfigure -+++ b/aconfigure -@@ -7908,6 +7908,9 @@ fi - # Check whether --with-opencore-amrnb was given. - if test "${with_opencore_amrnb+set}" = set; then : - withval=$with_opencore_amrnb; as_fn_error $? "This option is obsolete and replaced by --with-opencore-amr=DIR" "$LINENO" 5 -+else -+ true; -+ - fi - - -diff --git a/aconfigure.ac b/aconfigure.ac -index 3e88124..5d3e833 100644 ---- a/aconfigure.ac -+++ b/aconfigure.ac -@@ -1631,7 +1631,7 @@ AC_ARG_WITH(opencore-amrnb, - AC_HELP_STRING([--with-opencore-amrnb=DIR], - [This option is obsolete and replaced by --with-opencore-amr=DIR]), - [AC_MSG_ERROR(This option is obsolete and replaced by --with-opencore-amr=DIR)], -- [] -+ [true;] - ) - - dnl # opencore-amr alt prefix --- -2.5.0 - diff --git a/third-party/versions.mak b/third-party/versions.mak index 7b8b59c53..ca40531df 100644 --- a/third-party/versions.mak +++ b/third-party/versions.mak @@ -1,2 +1,2 @@ -PJPROJECT_VERSION = 2.4.5 +PJPROJECT_VERSION = 2.5 |