summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES11
-rw-r--r--apps/app_dial.c3
-rw-r--r--apps/app_queue.c9
-rw-r--r--cdr/cdr_custom.c2
-rw-r--r--cdr/cdr_syslog.c2
-rw-r--r--cel/cel_custom.c2
-rw-r--r--configs/samples/res_odbc.conf.sample5
-rw-r--r--contrib/ast-db-manage/config/versions/81b01a191a46_pjsip_add_contact_reg_server.py2
-rw-r--r--main/bridge_channel.c3
-rw-r--r--main/channel.c3
-rw-r--r--main/dial.c14
-rw-r--r--main/logger.c1
-rw-r--r--res/res_odbc.c232
-rw-r--r--res/res_pjsip/pjsip_distributor.c6
-rw-r--r--res/res_pjsip_mwi_body_generator.c4
-rw-r--r--res/res_srtp.c8
-rw-r--r--third-party/pjproject/patches/0001-2.4.5-fix-for-tls-async-ops.patch224
-rw-r--r--third-party/pjproject/patches/0001-Bump-tcp-tls-and-transaction-log-levels-from-1-to-3.patch70
-rw-r--r--third-party/pjproject/patches/0001-ioqueue-Enable-epoll-in-aconfigure.ac.patch80
-rw-r--r--third-party/pjproject/patches/0001-pjsip-apps-src-python-setup.py-Take-make-from-the-en.patch51
-rw-r--r--third-party/pjproject/patches/0001-sip_parser.c-Fix-pjsip_VIA_PARAM_SPEC_ESC.patch30
-rw-r--r--third-party/pjproject/patches/0001-sip_parser.c-Remove-wholesale-strip-from-parse_param.patch55
-rw-r--r--third-party/pjproject/patches/0001-sip_transport-Search-for-transport-even-if-listener-.patch114
-rw-r--r--third-party/pjproject/patches/0001-sip_transport_tcp-tls-Set-factory-on-transports-crea.patch48
-rw-r--r--third-party/pjproject/patches/0002-aconfigure.ac-Fix-autoconf-issue-with-opencore-amrnb.patch48
-rw-r--r--third-party/versions.mak2
26 files changed, 289 insertions, 740 deletions
diff --git a/CHANGES b/CHANGES
index 912dc7f73..518ee81d7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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,
-- &param->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