summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_sip.c2
-rw-r--r--include/asterisk/res_pjsip.h9
-rw-r--r--res/res_pjsip.c92
-rw-r--r--res/res_pjsip_session.c36
-rw-r--r--res/res_rtp_asterisk.c207
-rw-r--r--res/res_sorcery_memory_cache.c5
6 files changed, 254 insertions, 97 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 96609d218..412a25764 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -24926,10 +24926,12 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req,
if (ast_bridge_impart(bridge, c, replaces_chan, NULL,
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
ast_hangup(c);
+ ast_channel_unref(c);
}
} else {
ast_channel_move(replaces_chan, c);
ast_hangup(c);
+ ast_channel_unref(c);
}
sip_pvt_lock(p);
return 0;
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 9475d6d22..f199b8fef 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -2044,4 +2044,13 @@ unsigned int ast_sip_get_max_initial_qualify_time(void);
const char *ast_sip_get_contact_status_label(const enum ast_sip_contact_status_type status);
const char *ast_sip_get_contact_short_status_label(const enum ast_sip_contact_status_type status);
+/*!
+ * \brief Set a request to use the next value in the list of resolved addresses.
+ *
+ * \param tdata the tx data from the original request
+ * \retval 0 No more addresses to try
+ * \retval 1 The request was successfully re-intialized
+ */
+int ast_sip_failover_request(pjsip_tx_data *tdata);
+
#endif /* _RES_PJSIP_H */
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index bb5bc0390..6d7e4f739 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -3135,19 +3135,88 @@ static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint,
return ret_val;
}
+int ast_sip_failover_request(pjsip_tx_data *tdata)
+{
+ pjsip_via_hdr *via;
+
+ if (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1) {
+ /* No more addresses to try */
+ return 0;
+ }
+
+ /* Try next address */
+ ++tdata->dest_info.cur_addr;
+
+ via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
+ via->branch_param.slen = 0;
+
+ pjsip_tx_data_invalidate_msg(tdata);
+
+ return 1;
+}
+
+static void send_request_cb(void *token, pjsip_event *e);
+
+static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
+{
+ struct ast_sip_endpoint *endpoint;
+ pjsip_transaction *tsx;
+ pjsip_tx_data *tdata;
+ int res = 0;
+
+ if (!(endpoint = ao2_bump(req_data->endpoint))) {
+ return 0;
+ }
+
+ tsx = e->body.tsx_state.tsx;
+
+ switch (tsx->status_code) {
+ case 401:
+ case 407:
+ /* Resend the request with a challenge response if we are challenged. */
+ res = ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
+ && !ast_sip_create_request_with_auth(&endpoint->outbound_auths,
+ e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
+ break;
+ case 408:
+ case 503:
+ if ((res = ast_sip_failover_request(tsx->last_tx))) {
+ tdata = tsx->last_tx;
+ /*
+ * Bump the ref since it will be on a new transaction and
+ * we don't want it to go away along with the old transaction.
+ */
+ pjsip_tx_data_add_ref(tdata);
+ }
+ break;
+ }
+
+ if (res) {
+ res = endpt_send_request(endpoint, tdata, -1,
+ req_data, send_request_cb) == PJ_SUCCESS;
+ }
+
+ ao2_ref(endpoint, -1);
+ return res;
+}
+
static void send_request_cb(void *token, pjsip_event *e)
{
struct send_request_data *req_data = token;
- pjsip_transaction *tsx;
pjsip_rx_data *challenge;
- pjsip_tx_data *tdata;
struct ast_sip_supplement *supplement;
- struct ast_sip_endpoint *endpoint;
- int res;
switch(e->body.tsx_state.type) {
case PJSIP_EVENT_TRANSPORT_ERROR:
case PJSIP_EVENT_TIMER:
+ /*
+ * Check the request status on transport error or timeout. A transport
+ * error can occur when a TCP socket closes and that can be the result
+ * of a 503. Also we may need to failover on a timeout (408).
+ */
+ if (check_request_status(req_data, e)) {
+ return;
+ }
break;
case PJSIP_EVENT_RX_MSG:
challenge = e->body.tsx_state.src.rdata;
@@ -3166,20 +3235,9 @@ static void send_request_cb(void *token, pjsip_event *e)
}
AST_RWLIST_UNLOCK(&supplements);
- /* Resend the request with a challenge response if we are challenged. */
- tsx = e->body.tsx_state.tsx;
- endpoint = ao2_bump(req_data->endpoint);
- res = (tsx->status_code == 401 || tsx->status_code == 407)
- && endpoint
- && ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
- && !ast_sip_create_request_with_auth(&endpoint->outbound_auths,
- challenge, tsx->last_tx, &tdata)
- && endpt_send_request(endpoint, tdata, -1, req_data, send_request_cb)
- == PJ_SUCCESS;
- ao2_cleanup(endpoint);
- if (res) {
+ if (check_request_status(req_data, e)) {
/*
- * Request with challenge response sent.
+ * Request with challenge response or failover sent.
* Passed our req_data ref to the new request.
*/
return;
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index bbd74eeb5..c72959400 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2267,6 +2267,29 @@ static int session_end(struct ast_sip_session *session)
return 0;
}
+static int check_request_status(pjsip_inv_session *inv, pjsip_event *e)
+{
+ struct ast_sip_session *session = inv->mod_data[session_module.id];
+ pjsip_transaction *tsx = e->body.tsx_state.tsx;
+
+ if (tsx->status_code != 503 && tsx->status_code != 408) {
+ return 0;
+ }
+
+ if (!ast_sip_failover_request(tsx->last_tx)) {
+ return 0;
+ }
+
+ pjsip_inv_uac_restart(inv, PJ_FALSE);
+ /*
+ * Bump the ref since it will be on a new transaction and
+ * we don't want it to go away along with the old transaction.
+ */
+ pjsip_tx_data_add_ref(tsx->last_tx);
+ ast_sip_session_send_request(session, tsx->last_tx);
+ return 1;
+}
+
static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
{
struct ast_sip_session *session = inv->mod_data[session_module.id];
@@ -2299,11 +2322,20 @@ static void session_inv_on_state_changed(pjsip_inv_session *inv, pjsip_event *e)
handle_outgoing(session, e->body.tsx_state.src.tdata);
break;
case PJSIP_EVENT_RX_MSG:
- handle_incoming(session, e->body.tsx_state.src.rdata, type,
- AST_SIP_SESSION_BEFORE_MEDIA);
+ if (!check_request_status(inv, e)) {
+ handle_incoming(session, e->body.tsx_state.src.rdata, type,
+ AST_SIP_SESSION_BEFORE_MEDIA);
+ }
break;
case PJSIP_EVENT_TRANSPORT_ERROR:
case PJSIP_EVENT_TIMER:
+ /*
+ * Check the request status on transport error or timeout. A transport
+ * error can occur when a TCP socket closes and that can be the result
+ * of a 503. Also we may need to failover on a timeout (408).
+ */
+ check_request_status(inv, e);
+ break;
case PJSIP_EVENT_USER:
case PJSIP_EVENT_UNKNOWN:
case PJSIP_EVENT_TSX_STATE:
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 2e9d7e35e..c9270ed18 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -204,11 +204,13 @@ struct rtp_learning_info {
#ifdef HAVE_OPENSSL_SRTP
struct dtls_details {
+ ast_mutex_t lock; /*!< Lock for timeout timer synchronization */
SSL *ssl; /*!< SSL session */
BIO *read_bio; /*!< Memory buffer for reading */
BIO *write_bio; /*!< Memory buffer for writing */
enum ast_rtp_dtls_setup dtls_setup; /*!< Current setup state */
enum ast_rtp_dtls_connection connection; /*!< Whether this is a new or existing connection */
+ int timeout_timer; /*!< Scheduler id for timeout timer */
};
#endif
@@ -317,7 +319,6 @@ struct ast_rtp {
#ifdef HAVE_OPENSSL_SRTP
SSL_CTX *ssl_ctx; /*!< SSL context */
- ast_mutex_t dtls_timer_lock; /*!< Lock for synchronization purposes */
enum ast_rtp_dtls_verify dtls_verify; /*!< What to verify */
enum ast_srtp_suite suite; /*!< SRTP crypto suite */
enum ast_rtp_dtls_hash local_hash; /*!< Local hash used for the fingerprint */
@@ -326,7 +327,6 @@ struct ast_rtp {
unsigned char remote_fingerprint[EVP_MAX_MD_SIZE]; /*!< Fingerprint of the peer certificate */
unsigned int rekey; /*!< Interval at which to renegotiate and rekey */
int rekeyid; /*!< Scheduled item id for rekeying */
- int dtlstimerid; /*!< Scheduled item id for DTLS retransmission for RTP */
struct dtls_details dtls; /*!< DTLS state information */
#endif
};
@@ -444,6 +444,8 @@ static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level);
#ifdef HAVE_OPENSSL_SRTP
static int ast_rtp_activate(struct ast_rtp_instance *instance);
static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
+static void dtls_srtp_start_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
+static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
#endif
static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *ice, int use_srtp);
@@ -1229,6 +1231,9 @@ static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx,
}
dtls->connection = AST_RTP_DTLS_CONNECTION_NEW;
+ ast_mutex_init(&dtls->lock);
+ dtls->timeout_timer = -1;
+
return 0;
error:
@@ -1397,6 +1402,8 @@ static void ast_rtp_dtls_stop(struct ast_rtp_instance *instance)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ dtls_srtp_stop_timeout_timer(instance, rtp, 0);
+
if (rtp->ssl_ctx) {
SSL_CTX_free(rtp->ssl_ctx);
rtp->ssl_ctx = NULL;
@@ -1405,11 +1412,17 @@ static void ast_rtp_dtls_stop(struct ast_rtp_instance *instance)
if (rtp->dtls.ssl) {
SSL_free(rtp->dtls.ssl);
rtp->dtls.ssl = NULL;
+ ast_mutex_destroy(&rtp->dtls.lock);
}
- if (rtp->rtcp && rtp->rtcp->dtls.ssl) {
- SSL_free(rtp->rtcp->dtls.ssl);
- rtp->rtcp->dtls.ssl = NULL;
+ if (rtp->rtcp) {
+ dtls_srtp_stop_timeout_timer(instance, rtp, 1);
+
+ if (rtp->rtcp->dtls.ssl) {
+ SSL_free(rtp->rtcp->dtls.ssl);
+ rtp->rtcp->dtls.ssl = NULL;
+ ast_mutex_destroy(&rtp->rtcp->dtls.lock);
+ }
}
}
@@ -1586,21 +1599,25 @@ static void dtls_perform_handshake(struct ast_rtp_instance *instance, struct dtl
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
- if (!dtls->ssl) {
+ /* If we are not acting as a client connecting to the remote side then
+ * don't start the handshake as it will accomplish nothing and would conflict
+ * with the handshake we receive from the remote side.
+ */
+ if (!dtls->ssl || (dtls->dtls_setup != AST_RTP_DTLS_SETUP_ACTIVE)) {
return;
}
- if (SSL_is_init_finished(dtls->ssl)) {
- SSL_clear(dtls->ssl);
- if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
- SSL_set_accept_state(dtls->ssl);
- } else {
- SSL_set_connect_state(dtls->ssl);
- }
- dtls->connection = AST_RTP_DTLS_CONNECTION_NEW;
- }
SSL_do_handshake(dtls->ssl);
+
+ /* Since the handshake is started in a thread outside of the channel thread it's possible
+ * for the response to be handled in the channel thread before we start the timeout timer.
+ * To ensure this doesn't actually happen we hold the DTLS lock. The channel thread will
+ * block until we're done at which point the timeout timer will be immediately stopped.
+ */
+ ast_mutex_lock(&dtls->lock);
dtls_srtp_check_pending(instance, rtp, rtcp);
+ dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
+ ast_mutex_unlock(&dtls->lock);
}
#endif
@@ -1754,48 +1771,83 @@ static inline int rtcp_debug_test_addr(struct ast_sockaddr *addr)
}
#ifdef HAVE_OPENSSL_SRTP
-
-static int dtls_srtp_handle_timeout(const void *data)
+static int dtls_srtp_handle_timeout(struct ast_rtp_instance *instance, int rtcp)
{
- struct ast_rtp_instance *instance = (struct ast_rtp_instance *)data;
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
+ struct timeval dtls_timeout;
+
+ DTLSv1_handle_timeout(dtls->ssl);
+ dtls_srtp_check_pending(instance, rtp, rtcp);
- if (!rtp)
- {
+ /* If a timeout can't be retrieved then this recurring scheduled item must stop */
+ if (!DTLSv1_get_timeout(dtls->ssl, &dtls_timeout)) {
+ dtls->timeout_timer = -1;
return 0;
}
- ast_mutex_lock(&rtp->dtls_timer_lock);
- if (rtp->dtlstimerid == -1)
- {
- ast_mutex_unlock(&rtp->dtls_timer_lock);
+ return dtls_timeout.tv_sec * 1000 + dtls_timeout.tv_usec / 1000;
+}
+
+static int dtls_srtp_handle_rtp_timeout(const void *data)
+{
+ struct ast_rtp_instance *instance = (struct ast_rtp_instance *)data;
+ int reschedule;
+
+ reschedule = dtls_srtp_handle_timeout(instance, 0);
+
+ if (!reschedule) {
ao2_ref(instance, -1);
- return 0;
}
- rtp->dtlstimerid = -1;
- ast_mutex_unlock(&rtp->dtls_timer_lock);
+ return reschedule;
+}
+
+static int dtls_srtp_handle_rtcp_timeout(const void *data)
+{
+ struct ast_rtp_instance *instance = (struct ast_rtp_instance *)data;
+ int reschedule;
+
+ reschedule = dtls_srtp_handle_timeout(instance, 1);
- if (rtp->dtls.ssl && !SSL_is_init_finished(rtp->dtls.ssl)) {
- DTLSv1_handle_timeout(rtp->dtls.ssl);
+ if (!reschedule) {
+ ao2_ref(instance, -1);
}
- dtls_srtp_check_pending(instance, rtp, 0);
- if (rtp->rtcp && rtp->rtcp->dtls.ssl && !SSL_is_init_finished(rtp->rtcp->dtls.ssl)) {
- DTLSv1_handle_timeout(rtp->rtcp->dtls.ssl);
+ return reschedule;
+}
+
+static void dtls_srtp_start_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp)
+{
+ struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
+ struct timeval dtls_timeout;
+
+ if (DTLSv1_get_timeout(dtls->ssl, &dtls_timeout)) {
+ int timeout = dtls_timeout.tv_sec * 1000 + dtls_timeout.tv_usec / 1000;
+
+ ast_assert(dtls->timeout_timer == -1);
+
+ ao2_ref(instance, +1);
+ if ((dtls->timeout_timer = ast_sched_add(rtp->sched, timeout,
+ !rtcp ? dtls_srtp_handle_rtp_timeout : dtls_srtp_handle_rtcp_timeout, instance)) < 0) {
+ ao2_ref(instance, -1);
+ ast_log(LOG_WARNING, "Scheduling '%s' DTLS retransmission for RTP instance [%p] failed.\n",
+ !rtcp ? "RTP" : "RTCP", instance);
+ }
}
- dtls_srtp_check_pending(instance, rtp, 1);
+}
- ao2_ref(instance, -1);
+static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp)
+{
+ struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
- return 0;
+ AST_SCHED_DEL_UNREF(rtp->sched, dtls->timeout_timer, ao2_ref(instance, -1));
}
static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp)
{
struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
size_t pending;
- struct timeval dtls_timeout; /* timeout on DTLS */
if (!dtls->ssl || !dtls->write_bio) {
return;
@@ -1821,24 +1873,6 @@ static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct as
}
out = BIO_read(dtls->write_bio, outgoing, sizeof(outgoing));
-
- /* Stop existing DTLS timer if running */
- ast_mutex_lock(&rtp->dtls_timer_lock);
- if (rtp->dtlstimerid > -1) {
- AST_SCHED_DEL_UNREF(rtp->sched, rtp->dtlstimerid, ao2_ref(instance, -1));
- rtp->dtlstimerid = -1;
- }
-
- if (DTLSv1_get_timeout(dtls->ssl, &dtls_timeout)) {
- int timeout = dtls_timeout.tv_sec * 1000 + dtls_timeout.tv_usec / 1000;
- ao2_ref(instance, +1);
- if ((rtp->dtlstimerid = ast_sched_add(rtp->sched, timeout, dtls_srtp_handle_timeout, instance)) < 0) {
- ao2_ref(instance, -1);
- ast_log(LOG_WARNING, "scheduling DTLS retransmission for RTP instance [%p] failed.\n", instance);
- }
- }
- ast_mutex_unlock(&rtp->dtls_timer_lock);
-
__rtp_sendto(instance, outgoing, out, 0, &remote_address, rtcp, &ice, 0);
}
}
@@ -2014,8 +2048,6 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
}
#ifdef HAVE_OPENSSL_SRTP
- dtls_srtp_check_pending(instance, rtp, rtcp);
-
/* If this is an SSL packet pass it to OpenSSL for processing. RFC section for first byte value:
* https://tools.ietf.org/html/rfc5764#section-5.1.2 */
if ((*in >= 20) && (*in <= 63)) {
@@ -2029,6 +2061,15 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
return -1;
}
+ /* This mutex is locked so that this thread blocks until the dtls_perform_handshake function
+ * completes.
+ */
+ ast_mutex_lock(&dtls->lock);
+ ast_mutex_unlock(&dtls->lock);
+
+ /* Before we feed data into OpenSSL ensure that the timeout timer is either stopped or completed */
+ dtls_srtp_stop_timeout_timer(instance, rtp, rtcp);
+
/* If we don't yet know if we are active or passive and we receive a packet... we are obviously passive */
if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
dtls->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
@@ -2057,6 +2098,9 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
/* Use the keying material to set up key/salt information */
res = dtls_srtp_setup(rtp, srtp, instance);
}
+ } else {
+ /* Since we've sent additional traffic start the timeout timer for retransmission */
+ dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
}
return res;
@@ -2479,7 +2523,6 @@ static int ast_rtp_new(struct ast_rtp_instance *instance,
#ifdef HAVE_OPENSSL_SRTP
rtp->rekeyid = -1;
- rtp->dtlstimerid = -1;
#endif
rtp->f.subclass.format = ao2_bump(ast_format_none);
@@ -2497,6 +2540,10 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
struct timespec ts = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000, };
#endif
+#ifdef HAVE_OPENSSL_SRTP
+ ast_rtp_dtls_stop(instance);
+#endif
+
/* Destroy the smoother that was smoothing out audio if present */
if (rtp->smoother) {
ast_smoother_free(rtp->smoother);
@@ -2515,11 +2562,6 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
* RTP instance while it's active.
*/
close(rtp->rtcp->s);
-#ifdef HAVE_OPENSSL_SRTP
- if (rtp->rtcp->dtls.ssl) {
- SSL_free(rtp->rtcp->dtls.ssl);
- }
-#endif
ast_free(rtp->rtcp);
}
@@ -2571,18 +2613,6 @@ static int ast_rtp_destroy(struct ast_rtp_instance *instance)
}
#endif
-#ifdef HAVE_OPENSSL_SRTP
- /* Destroy the SSL context if present */
- if (rtp->ssl_ctx) {
- SSL_CTX_free(rtp->ssl_ctx);
- }
-
- /* Destroy the SSL session if present */
- if (rtp->dtls.ssl) {
- SSL_free(rtp->dtls.ssl);
- }
-#endif
-
ao2_cleanup(rtp->lasttxformat);
ao2_cleanup(rtp->lastrxformat);
ao2_cleanup(rtp->f.subclass.format);
@@ -4909,9 +4939,11 @@ static void ast_rtp_stop(struct ast_rtp_instance *instance)
#ifdef HAVE_OPENSSL_SRTP
AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
- ast_mutex_lock(&rtp->dtls_timer_lock);
- AST_SCHED_DEL_UNREF(rtp->sched, rtp->dtlstimerid, ao2_ref(instance, -1));
- ast_mutex_unlock(&rtp->dtls_timer_lock);
+
+ dtls_srtp_stop_timeout_timer(instance, rtp, 0);
+ if (rtp->rtcp) {
+ dtls_srtp_stop_timeout_timer(instance, rtp, 1);
+ }
#endif
if (rtp->rtcp && rtp->rtcp->schedid > 0) {
@@ -4993,10 +5025,31 @@ static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level)
}
#ifdef HAVE_OPENSSL_SRTP
+static void dtls_perform_setup(struct dtls_details *dtls)
+{
+ if (!dtls->ssl || !SSL_is_init_finished(dtls->ssl)) {
+ return;
+ }
+
+ SSL_clear(dtls->ssl);
+ if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+ SSL_set_accept_state(dtls->ssl);
+ } else {
+ SSL_set_connect_state(dtls->ssl);
+ }
+ dtls->connection = AST_RTP_DTLS_CONNECTION_NEW;
+}
+
static int ast_rtp_activate(struct ast_rtp_instance *instance)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ dtls_perform_setup(&rtp->dtls);
+
+ if (rtp->rtcp) {
+ dtls_perform_setup(&rtp->rtcp->dtls);
+ }
+
/* If ICE negotiation is enabled the DTLS Handshake will be performed upon completion of it */
#ifdef HAVE_PJPROJECT
if (rtp->ice) {
diff --git a/res/res_sorcery_memory_cache.c b/res/res_sorcery_memory_cache.c
index 7a07d14f0..e486a6400 100644
--- a/res/res_sorcery_memory_cache.c
+++ b/res/res_sorcery_memory_cache.c
@@ -2551,6 +2551,10 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
+ /* This causes the stale unit test to execute last, so if a sorcery instance persists
+ * longer than expected subsequent unit tests don't fail when setting it up.
+ */
+ AST_TEST_REGISTER(stale);
AST_TEST_REGISTER(open_with_valid_options);
AST_TEST_REGISTER(open_with_invalid_options);
AST_TEST_REGISTER(create_and_retrieve);
@@ -2558,7 +2562,6 @@ static int load_module(void)
AST_TEST_REGISTER(delete);
AST_TEST_REGISTER(maximum_objects);
AST_TEST_REGISTER(expiration);
- AST_TEST_REGISTER(stale);
return AST_MODULE_LOAD_SUCCESS;
}