diff options
-rw-r--r-- | CHANGES | 17 | ||||
-rw-r--r-- | apps/app_voicemail.c | 2 | ||||
-rw-r--r-- | cdr/cdr_radius.c | 12 | ||||
-rw-r--r-- | cel/cel_radius.c | 12 | ||||
-rw-r--r-- | channels/chan_pjsip.c | 237 | ||||
-rw-r--r-- | configs/samples/pjsip.conf.sample | 2 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/versions/4468b4a91372_add_pjsip_asymmetric_rtp_codec.py | 31 | ||||
-rw-r--r-- | include/asterisk/res_pjsip.h | 2 | ||||
-rw-r--r-- | res/res_pjsip.c | 8 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_configuration.c | 1 | ||||
-rw-r--r-- | res/res_pjsip_caller_id.c | 14 | ||||
-rw-r--r-- | res/res_pjsip_sdp_rtp.c | 5 | ||||
-rw-r--r-- | tests/test_astobj2_thrash.c | 11 | ||||
-rw-r--r-- | third-party/pjproject/Makefile | 7 | ||||
-rw-r--r-- | third-party/pjproject/patches/0000-remove-third-party.patch | 5 |
15 files changed, 302 insertions, 64 deletions
@@ -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@ |