summaryrefslogtreecommitdiff
path: root/res/res_rtp_asterisk.c
diff options
context:
space:
mode:
authorserver-pandora <server-pandora@xencall.com>2015-12-14 11:53:20 -0800
committerMatt Jordan <mjordan@digium.com>2015-12-15 07:31:12 -0600
commit24ae124e4f7310cfa64c187b944b2ffc060da28d (patch)
tree51813b001eb95dfb948e5c9d48d3fa019bdf16c5 /res/res_rtp_asterisk.c
parent36097a185db00230a89f019b9b8ee2d478cc6665 (diff)
res_rtp_asterisk.c: Fix DTLS negotiation delays.
- Trigger pending DTLS packets to send out, once the RTP instance's remote address is set. - Avoids locking the DTLS structure unnecessarily by only doing this if DTLS is passive. - Add DTLS locks around the structurally sensitive calls in the SSL portion of __rtp_recvfrom, since dtls_srtp_check_pending does not lock inside of itself, and we're dealing with the SSL BIO in at least two threads. WebRTC channels may receive a DTLS handshake before ast_rtp_remote_address_set is called, which causes there to be a pending response to send out. Previous to 1ad827, this was handled by calling dtls_srtp_check_pending on receipt of any RTP packet - a STUN or RTP packet could trigger the pending handshake response. Since that was rightfully removed, whenever the DTLS handshake is received before the remote address is set, we would have to wait until another SSL packet arrives. As of Chrome M47's optimizations to their handshake process, WebRTC conversations between Chrome M47+ and Asterisk, where Asterisk is passive, experience a 1 second delay without this patch, because the SSL handshake is received before ICE negotation stores the remote_address, and the next SSL packet isn't received until after a 1 second timeout in Chrome, which causes a new handshake request. ASTERISK-25614 #close Change-Id: I547f1be7e302dbf71f6553dd8cbc0657b1d0b908
Diffstat (limited to 'res/res_rtp_asterisk.c')
-rw-r--r--res/res_rtp_asterisk.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index f6bf34211..3dfaf87fa 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -2118,6 +2118,8 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
SSL_set_accept_state(dtls->ssl);
}
+ ast_mutex_lock(&dtls->lock);
+
dtls_srtp_check_pending(instance, rtp, rtcp);
BIO_write(dtls->read_bio, buf, len);
@@ -2128,6 +2130,7 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
unsigned long error = ERR_get_error();
ast_log(LOG_ERROR, "DTLS failure occurred on RTP instance '%p' due to reason '%s', terminating\n",
instance, ERR_reason_error_string(error));
+ ast_mutex_unlock(&dtls->lock);
return -1;
}
@@ -2145,6 +2148,8 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
}
+ ast_mutex_unlock(&dtls->lock);
+
return res;
}
#endif
@@ -4817,6 +4822,9 @@ static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
{
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+#ifdef HAVE_OPENSSL_SRTP
+ struct dtls_details *dtls;
+#endif
if (rtp->rtcp) {
ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
@@ -4834,6 +4842,28 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
rtp_learning_seq_init(&rtp->rtp_source_learn, rtp->seqno);
}
+#ifdef HAVE_OPENSSL_SRTP
+ /* Trigger pending outbound DTLS packets received before the address was set. Avoid unnecessary locking
+ * by checking if we're passive. Without this, we only send the pending packets once a new SSL packet is
+ * received in __rtp_recvfrom.
+ */
+ dtls = &rtp->dtls;
+ if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+ ast_mutex_lock(&dtls->lock);
+ dtls_srtp_check_pending(instance, rtp, 0);
+ ast_mutex_unlock(&dtls->lock);
+ }
+
+ if (rtp->rtcp) {
+ dtls = &rtp->rtcp->dtls;
+ if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+ ast_mutex_lock(&dtls->lock);
+ dtls_srtp_check_pending(instance, rtp, 1);
+ ast_mutex_unlock(&dtls->lock);
+ }
+ }
+#endif
+
return;
}