summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES17
-rw-r--r--apps/app_voicemail.c2
-rw-r--r--cdr/cdr_radius.c12
-rw-r--r--cel/cel_radius.c12
-rw-r--r--channels/chan_pjsip.c237
-rw-r--r--configs/samples/pjsip.conf.sample2
-rw-r--r--contrib/ast-db-manage/config/versions/4468b4a91372_add_pjsip_asymmetric_rtp_codec.py31
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--res/res_pjsip.c8
-rw-r--r--res/res_pjsip/pjsip_configuration.c1
-rw-r--r--res/res_pjsip_caller_id.c14
-rw-r--r--res/res_pjsip_sdp_rtp.c5
-rw-r--r--tests/test_astobj2_thrash.c11
-rw-r--r--third-party/pjproject/Makefile7
-rw-r--r--third-party/pjproject/patches/0000-remove-third-party.patch5
15 files changed, 302 insertions, 64 deletions
diff --git a/CHANGES b/CHANGES
index 622973c48..c9126e16b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -34,6 +34,16 @@ res_pjsip
preferred codec rather than advertising all joint codec capabilities.
This limits the other side's codec choice to exactly what we prefer.
+cdr_radius
+------------------
+ * To fix a memory leak the syslog channel is now empty if it has not been set
+ and used by a syslog channel in the logger.
+
+cel_radius
+------------------
+ * To fix a memory leak the syslog channel is now empty if it has not been set
+ and used by a syslog channel in the logger.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ----------
------------------------------------------------------------------------------
@@ -47,6 +57,13 @@ res_pjsip
res_pjsip_multihomed module has also been moved into core res_pjsip to ensure
that messages are updated with the correct address information in all cases.
+chan_pjsip
+------------------
+ * The default behavior for RTP codecs has been changed. The sending codec will
+ now match the receiving codec. This can be turned off and behavior reverted
+ to asymmetric using the "asymmetric_rtp_codec" endpoint option. If this
+ option is set then the sending and received codec are allowed to differ.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ----------
------------------------------------------------------------------------------
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 4727e2ee5..300dc186d 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -12529,6 +12529,7 @@ static int vm_box_exists(struct ast_channel *chan, const char *data)
context++;
}
+ memset(&svm, 0, sizeof(svm));
vmu = find_user(&svm, context, args.mbox);
if (vmu) {
pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
@@ -12560,6 +12561,7 @@ static int acf_mailbox_exists(struct ast_channel *chan, const char *cmd, char *a
ast_log(AST_LOG_WARNING, "MAILBOX_EXISTS is deprecated. Please use ${VM_INFO(%s,exists)} instead.\n", args);
}
+ memset(&svm, 0, sizeof(svm));
vmu = find_user(&svm, ast_strlen_zero(arg.context) ? "default" : arg.context, arg.mbox);
ast_copy_string(buf, vmu ? "1" : "0", len);
free_user(vmu);
diff --git a/cdr/cdr_radius.c b/cdr/cdr_radius.c
index e1a639cda..ddde5b890 100644
--- a/cdr/cdr_radius.c
+++ b/cdr/cdr_radius.c
@@ -265,18 +265,6 @@ static int load_module(void)
} else
return AST_MODULE_LOAD_DECLINE;
- /*
- * start logging
- *
- * NOTE: Yes this causes a slight memory leak if the module is
- * unloaded. However, it is better than a crash if cdr_radius
- * and cel_radius are both loaded.
- */
- tmp = ast_strdup("asterisk");
- if (tmp) {
- rc_openlog((char *) tmp);
- }
-
/* read radiusclient-ng config file */
if (!(rh = rc_read_config(radiuscfg))) {
ast_log(LOG_NOTICE, "Cannot load radiusclient-ng configuration file %s.\n", radiuscfg);
diff --git a/cel/cel_radius.c b/cel/cel_radius.c
index 3c20e9780..f6ab89267 100644
--- a/cel/cel_radius.c
+++ b/cel/cel_radius.c
@@ -237,18 +237,6 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
- /*
- * start logging
- *
- * NOTE: Yes this causes a slight memory leak if the module is
- * unloaded. However, it is better than a crash if cdr_radius
- * and cel_radius are both loaded.
- */
- tmp = ast_strdup("asterisk");
- if (tmp) {
- rc_openlog((char *) tmp);
- }
-
/* read radiusclient-ng config file */
if (!(rh = rc_read_config(radiuscfg))) {
ast_log(LOG_NOTICE, "Cannot load radiusclient-ng configuration file %s.\n", radiuscfg);
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 00d4a1452..b0dba1b47 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -219,9 +219,7 @@ static enum ast_rtp_glue_result chan_pjsip_get_vrtp_peer(struct ast_channel *cha
/*! \brief Function called by RTP engine to get peer capabilities */
static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
{
- struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
-
- ast_format_cap_append_from_cap(result, channel->session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(result, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_UNKNOWN);
}
/*! \brief Destructor function for \ref transport_info_data */
@@ -559,6 +557,12 @@ static int answer(void *data)
struct ast_sip_session *session = data;
if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+ ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+ session->inv_session->cause,
+ pjsip_get_status_text(session->inv_session->cause)->ptr);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
return 0;
}
@@ -575,6 +579,10 @@ static int answer(void *data)
ast_sip_session_send_response(session, packet);
}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+
return (status == PJ_SUCCESS) ? 0 : -1;
}
@@ -591,12 +599,23 @@ static int chan_pjsip_answer(struct ast_channel *ast)
ast_setstate(ast, AST_STATE_UP);
session = ao2_bump(channel->session);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+ ao2_ref(session, -1);
+ return -1;
+ }
+#endif
+
/* the answer task needs to be pushed synchronously otherwise a race condition
can occur between this thread and bridging (specifically when native bridging
attempts to do direct media) */
ast_channel_unlock(ast);
if (ast_sip_push_task_synchronous(session->serializer, answer, session)) {
ast_log(LOG_WARNING, "Unable to push answer task to the threadpool. Cannot answer call\n");
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
ao2_ref(session, -1);
ast_channel_lock(ast);
return -1;
@@ -704,15 +723,28 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
session = channel->session;
- if (ast_format_cap_iscompatible_format(session->endpoint->media.codecs, f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
- ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when endpoint '%s' is not configured for it\n",
- ast_format_get_name(f->subclass.format), ast_channel_name(ast),
- ast_sorcery_object_get_id(session->endpoint));
+ if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when it has not been negotiated\n",
+ ast_format_get_name(f->subclass.format), ast_channel_name(ast));
ast_frfree(f);
return &ast_null_frame;
}
+ if (!session->endpoint->asymmetric_rtp_codec &&
+ ast_format_cmp(ast_channel_rawwriteformat(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
+ /* For maximum compatibility we ensure that the write format matches that of the received media */
+ ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n",
+ ast_format_get_name(f->subclass.format), ast_channel_name(ast),
+ ast_format_get_name(ast_channel_rawwriteformat(ast)));
+ ast_channel_set_rawwriteformat(ast, f->subclass.format);
+ ast_set_write_format(ast, ast_channel_writeformat(ast));
+
+ if (ast_channel_is_bridged(ast)) {
+ ast_channel_set_unbridged_nolock(ast, 1);
+ }
+ }
+
if (session->dsp) {
int dsp_features;
@@ -1105,6 +1137,9 @@ static int indicate(void *data)
ast_sip_session_send_response(session, packet);
}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
ao2_ref(ind_data, -1);
return 0;
@@ -1132,17 +1167,35 @@ static int transmit_info_with_vidupdate(void *data)
RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
struct pjsip_tx_data *tdata;
+ if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+ ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+ session->inv_session->cause,
+ pjsip_get_status_text(session->inv_session->cause)->ptr);
+ goto failure;
+ }
+
if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
ast_log(LOG_ERROR, "Could not create text video update INFO request\n");
- return -1;
+ goto failure;
}
if (ast_sip_add_body(tdata, &body)) {
ast_log(LOG_ERROR, "Could not add body to text video update INFO request\n");
- return -1;
+ goto failure;
}
ast_sip_session_send_request(session, tdata);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+
return 0;
+
+failure:
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+ return -1;
+
}
/*!
@@ -1185,6 +1238,17 @@ static int update_connected_line_information(void *data)
{
struct ast_sip_session *session = data;
+ if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+ ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+ session->inv_session->cause,
+ pjsip_get_status_text(session->inv_session->cause)->ptr);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+ ao2_ref(session, -1);
+ return -1;
+ }
+
if (ast_channel_state(session->channel) == AST_STATE_UP
|| session->inv_session->role == PJSIP_ROLE_UAC) {
if (is_colp_update_allowed(session)) {
@@ -1222,6 +1286,10 @@ static int update_connected_line_information(void *data)
}
}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+
ao2_ref(session, -1);
return 0;
}
@@ -1335,10 +1403,18 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
res = ast_rtp_instance_write(media->rtp, &fr);
} else {
ao2_ref(channel->session, +1);
-
- if (ast_sip_push_task(channel->session->serializer, transmit_info_with_vidupdate, channel->session)) {
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(channel->session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
ao2_cleanup(channel->session);
+ } else {
+#endif
+ if (ast_sip_push_task(channel->session->serializer, transmit_info_with_vidupdate, channel->session)) {
+ ao2_cleanup(channel->session);
+ }
+#ifdef HAVE_PJSIP_INV_SESSION_REF
}
+#endif
}
ast_test_suite_event_notify("AST_CONTROL_VIDUPDATE", "Result: Success");
} else {
@@ -1348,7 +1424,17 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
break;
case AST_CONTROL_CONNECTED_LINE:
ao2_ref(channel->session, +1);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(channel->session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+ ao2_cleanup(channel->session);
+ return -1;
+ }
+#endif
if (ast_sip_push_task(channel->session->serializer, update_connected_line_information, channel->session)) {
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(channel->session->inv_session);
+#endif
ao2_cleanup(channel->session);
}
break;
@@ -1441,9 +1527,23 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
if (response_code) {
struct indicate_data *ind_data = indicate_data_alloc(channel->session, condition, response_code, data, datalen);
- if (!ind_data || ast_sip_push_task(channel->session->serializer, indicate, ind_data)) {
+
+ if (!ind_data) {
+ return -1;
+ }
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(ind_data->session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+ ao2_cleanup(ind_data);
+ return -1;
+ }
+#endif
+ if (ast_sip_push_task(channel->session->serializer, indicate, ind_data)) {
ast_log(LOG_NOTICE, "Cannot send response code %d to endpoint %s. Could not queue task properly\n",
response_code, ast_sorcery_object_get_id(channel->session->endpoint));
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(ind_data->session->inv_session);
+#endif
ao2_cleanup(ind_data);
res = -1;
}
@@ -1564,21 +1664,31 @@ static int transfer(void *data)
struct ast_sip_contact *contact = NULL;
const char *target = trnf_data->target;
- /* See if we have an endpoint; if so, use its contact */
- endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", target);
- if (endpoint) {
- contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
- if (contact && !ast_strlen_zero(contact->uri)) {
- target = contact->uri;
+ if (trnf_data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+ ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+ trnf_data->session->inv_session->cause,
+ pjsip_get_status_text(trnf_data->session->inv_session->cause)->ptr);
+ } else {
+ /* See if we have an endpoint; if so, use its contact */
+ endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", target);
+ if (endpoint) {
+ contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);
+ if (contact && !ast_strlen_zero(contact->uri)) {
+ target = contact->uri;
+ }
}
- }
- if (ast_channel_state(trnf_data->session->channel) == AST_STATE_RING) {
- transfer_redirect(trnf_data->session, target);
- } else {
- transfer_refer(trnf_data->session, target);
+ if (ast_channel_state(trnf_data->session->channel) == AST_STATE_RING) {
+ transfer_redirect(trnf_data->session, target);
+ } else {
+ transfer_refer(trnf_data->session, target);
+ }
}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(trnf_data->session->inv_session);
+#endif
+
ao2_ref(trnf_data, -1);
ao2_cleanup(endpoint);
ao2_cleanup(contact);
@@ -1595,8 +1705,19 @@ static int chan_pjsip_transfer(struct ast_channel *chan, const char *target)
return -1;
}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(trnf_data->session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+ ao2_cleanup(trnf_data);
+ return -1;
+ }
+#endif
+
if (ast_sip_push_task(channel->session->serializer, transfer, trnf_data)) {
ast_log(LOG_WARNING, "Error requesting transfer\n");
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(trnf_data->session->inv_session);
+#endif
ao2_cleanup(trnf_data);
return -1;
}
@@ -1678,9 +1799,16 @@ static int transmit_info_dtmf(void *data)
.subtype = "dtmf-relay",
};
+ if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+ ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+ session->inv_session->cause,
+ pjsip_get_status_text(session->inv_session->cause)->ptr);
+ goto failure;
+ }
+
if (!(body_text = ast_str_create(32))) {
ast_log(LOG_ERROR, "Could not allocate buffer for INFO DTMF.\n");
- return -1;
+ goto failure;
}
ast_str_set(&body_text, 0, "Signal=%c\r\nDuration=%u\r\n", dtmf_data->digit, dtmf_data->duration);
@@ -1688,16 +1816,27 @@ static int transmit_info_dtmf(void *data)
if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
ast_log(LOG_ERROR, "Could not create DTMF INFO request\n");
- return -1;
+ goto failure;
}
if (ast_sip_add_body(tdata, &body)) {
ast_log(LOG_ERROR, "Could not add body to DTMF INFO request\n");
pjsip_tx_data_dec_ref(tdata);
- return -1;
+ goto failure;
}
ast_sip_session_send_request(session, tdata);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+
return 0;
+
+failure:
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(session->inv_session);
+#endif
+ return -1;
+
}
/*! \brief Function called by core to stop a DTMF digit */
@@ -1717,8 +1856,19 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
return -1;
}
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(dtmf_data->session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+ ao2_cleanup(dtmf_data);
+ return -1;
+ }
+#endif
+
if (ast_sip_push_task(channel->session->serializer, transmit_info_dtmf, dtmf_data)) {
ast_log(LOG_WARNING, "Error sending DTMF via INFO.\n");
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(dtmf_data->session->inv_session);
+#endif
ao2_cleanup(dtmf_data);
return -1;
}
@@ -2064,11 +2214,21 @@ static int sendtext(void *obj)
.body_text = data->text
};
- ast_debug(3, "Sending in dialog SIP message\n");
+ if (data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
+ ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
+ data->session->inv_session->cause,
+ pjsip_get_status_text(data->session->inv_session->cause)->ptr);
+ } else {
+ ast_debug(3, "Sending in dialog SIP message\n");
+
+ ast_sip_create_request("MESSAGE", data->session->inv_session->dlg, data->session->endpoint, NULL, NULL, &tdata);
+ ast_sip_add_body(tdata, &body);
+ ast_sip_send_request(tdata, data->session->inv_session->dlg, data->session->endpoint, NULL, NULL);
+ }
- ast_sip_create_request("MESSAGE", data->session->inv_session->dlg, data->session->endpoint, NULL, NULL, &tdata);
- ast_sip_add_body(tdata, &body);
- ast_sip_send_request(tdata, data->session->inv_session->dlg, data->session->endpoint, NULL, NULL);
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(data->session->inv_session);
+#endif
return 0;
}
@@ -2079,7 +2239,22 @@ static int chan_pjsip_sendtext(struct ast_channel *ast, const char *text)
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
struct sendtext_data *data = sendtext_data_create(channel->session, text);
- if (!data || ast_sip_push_task(channel->session->serializer, sendtext, data)) {
+ if (!data) {
+ return -1;
+ }
+
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ if (pjsip_inv_add_ref(data->session->inv_session) != PJ_SUCCESS) {
+ ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
+ ao2_ref(data, -1);
+ return -1;
+ }
+#endif
+
+ if (ast_sip_push_task(channel->session->serializer, sendtext, data)) {
+#ifdef HAVE_PJSIP_INV_SESSION_REF
+ pjsip_inv_dec_ref(data->session->inv_session);
+#endif
ao2_ref(data, -1);
return -1;
}
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 3bb9dc5bb..6595423c9 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -759,6 +759,8 @@
; rather than advertising all joint codec capabilities. This
; limits the other side's codec choice to exactly what we prefer.
; default is no.
+;asymmetric_rtp_codec= ; Allow the sending and receiving codec to differ and
+ ; not be automatically matched (default: "no")
;==========================AUTH SECTION OPTIONS=========================
;[auth]
diff --git a/contrib/ast-db-manage/config/versions/4468b4a91372_add_pjsip_asymmetric_rtp_codec.py b/contrib/ast-db-manage/config/versions/4468b4a91372_add_pjsip_asymmetric_rtp_codec.py
new file mode 100644
index 000000000..c121495e2
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/4468b4a91372_add_pjsip_asymmetric_rtp_codec.py
@@ -0,0 +1,31 @@
+"""add pjsip asymmetric rtp codec
+
+Revision ID: 4468b4a91372
+Revises: a6ef36f1309
+Create Date: 2016-10-25 10:57:20.808815
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4468b4a91372'
+down_revision = 'a6ef36f1309'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+ ############################# Enums ##############################
+
+ # yesno_values have already been created, so use postgres enum object
+ # type to get around "already created" issue - works okay with mysql
+ yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+ op.add_column('ps_endpoints', sa.Column('asymmetric_rtp_codec', yesno_values))
+
+
+def downgrade():
+ op.drop_column('ps_endpoints', 'asymmetric_rtp_codec')
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 92bdabb66..894ea76f5 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -759,6 +759,8 @@ struct ast_sip_endpoint {
char *contact_user;
/*! Whether to response SDP offer with single most preferred codec. */
unsigned int preferred_codec_only;
+ /*! Do we allow an asymmetric RTP codec? */
+ unsigned int asymmetric_rtp_codec;
};
/*!
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 39c365aa1..916c464a1 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -925,6 +925,14 @@
On outbound requests, force the user portion of the Contact header to this value.
</para></description>
</configOption>
+ <configOption name="asymmetric_rtp_codec" default="no">
+ <synopsis>Allow the sending and receiving RTP codec to differ</synopsis>
+ <description><para>
+ When set to "yes" the codec in use for sending will be allowed to differ from
+ that of the received one. PJSIP will not automatically switch the sending one
+ to the receiving one.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 186646759..00c223330 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1938,6 +1938,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "preferred_codec_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, preferred_codec_only));
+ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "asymmetric_rtp_codec", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, asymmetric_rtp_codec));
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index 16b19ec2b..7948d33be 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -523,8 +523,11 @@ static void add_pai_header(const struct ast_sip_session *session, pjsip_tx_data
}
}
- base = tdata->msg->type == PJSIP_REQUEST_MSG ? session->saved_from_hdr :
- PJSIP_MSG_TO_HDR(tdata->msg);
+ if (tdata->msg->type == PJSIP_REQUEST_MSG) {
+ base = session->saved_from_hdr ? session->saved_from_hdr : PJSIP_MSG_FROM_HDR(tdata->msg);
+ } else {
+ base = PJSIP_MSG_TO_HDR(tdata->msg);
+ }
pai_hdr = create_new_id_hdr(&pj_pai_name, base, tdata, id);
if (!pai_hdr) {
@@ -629,8 +632,11 @@ static void add_rpid_header(const struct ast_sip_session *session, pjsip_tx_data
}
}
- base = tdata->msg->type == PJSIP_REQUEST_MSG ? session->saved_from_hdr :
- PJSIP_MSG_TO_HDR(tdata->msg);
+ if (tdata->msg->type == PJSIP_REQUEST_MSG) {
+ base = session->saved_from_hdr ? session->saved_from_hdr : PJSIP_MSG_FROM_HDR(tdata->msg);
+ } else {
+ base = PJSIP_MSG_TO_HDR(tdata->msg);
+ }
rpid_hdr = create_new_id_hdr(&pj_rpid_name, base, tdata, id);
if (!rpid_hdr) {
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 71eba1464..6d6f3f12f 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -385,6 +385,11 @@ static int set_caps(struct ast_sip_session *session,
session->dsp = NULL;
}
}
+
+ if (ast_channel_is_bridged(session->channel)) {
+ ast_channel_set_unbridged_nolock(session->channel, 1);
+ }
+
ast_channel_unlock(session->channel);
}
diff --git a/tests/test_astobj2_thrash.c b/tests/test_astobj2_thrash.c
index eaadbb647..ef0da44ca 100644
--- a/tests/test_astobj2_thrash.c
+++ b/tests/test_astobj2_thrash.c
@@ -46,6 +46,13 @@ ASTERISK_REGISTER_FILE()
#include "asterisk/utils.h"
#define MAX_HASH_ENTRIES 15000
+/*
+ * Use one of the online calculators to find the first prime number
+ * greater than MAX_HASH_ENTRIES / 100.
+ */
+#define HASH_BUCKETS 151
+
+#define COUNT_SLEEP_US 500
#define MAX_TEST_SECONDS 60
struct hash_test {
@@ -207,7 +214,7 @@ static void *hash_test_count(void *d)
if (last_count == count) {
/* Allow other threads to run. */
- sched_yield();
+ usleep(COUNT_SLEEP_US);
} else if (last_count > count) {
/* Make sure the ao2 container never shrinks */
return "ao2 container unexpectedly shrank";
@@ -261,7 +268,7 @@ AST_TEST_DEFINE(hash_test)
data.preload = MAX_HASH_ENTRIES / 2;
data.max_grow = MAX_HASH_ENTRIES - data.preload;
data.deadline = ast_tvadd(ast_tvnow(), ast_tv(MAX_TEST_SECONDS, 0));
- data.to_be_thrashed = ao2_container_alloc(MAX_HASH_ENTRIES / 100, hash_string,
+ data.to_be_thrashed = ao2_container_alloc(HASH_BUCKETS, hash_string,
compare_strings);
if (data.to_be_thrashed == NULL) {
diff --git a/third-party/pjproject/Makefile b/third-party/pjproject/Makefile
index aaf69bff1..07a6c9cd6 100644
--- a/third-party/pjproject/Makefile
+++ b/third-party/pjproject/Makefile
@@ -1,6 +1,7 @@
.PHONY: _all all _install install clean distclean echo_cflags configure
include ../versions.mak
+export PJDIR := $(shell pwd -P)/source
SPECIAL_TARGETS :=
@@ -85,9 +86,9 @@ $(DOWNLOAD_DIR)/pjproject-$(PJPROJECT_VERSION).tar.bz2: ../versions.mak
source/.unpacked: $(DOWNLOAD_DIR)/pjproject-$(PJPROJECT_VERSION).tar.bz2
$(ECHO_PREFIX) Unpacking $<
- -@rm -rf source >/dev/null 2>&1
- -@mkdir source >/dev/null 2>&1
- $(CMD_PREFIX) $(TAR) --strip-components=1 -C source -xjf $<
+ -@rm -rf source pjproject-* >/dev/null 2>&1
+ $(CMD_PREFIX) $(TAR) -xjf $<
+ @mv pjproject-$(PJPROJECT_VERSION) source
$(ECHO_PREFIX) Applying patches
$(CMD_PREFIX) ./apply_patches $(QUIET_CONFIGURE) patches source
-@touch source/.unpacked
diff --git a/third-party/pjproject/patches/0000-remove-third-party.patch b/third-party/pjproject/patches/0000-remove-third-party.patch
index 131775195..aca7f0198 100644
--- a/third-party/pjproject/patches/0000-remove-third-party.patch
+++ b/third-party/pjproject/patches/0000-remove-third-party.patch
@@ -2,6 +2,11 @@ diff --git a/build.mak.in b/build.mak.in
index 802211c..006d887 100644
--- a/build.mak.in
+++ b/build.mak.in
+@@ -1,4 +1,3 @@
+-export PJDIR := @ac_pjdir@
+ include $(PJDIR)/version.mak
+ export PJ_DIR := $(PJDIR)
+
@@ -9,7 +9,7 @@ export HOST_NAME := unix
export CC_NAME := gcc
export TARGET_NAME := @target@