summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDade Brandon <dade@xencall.com>2015-12-17 17:05:00 -0800
committerDade Brandon <dade@xencall.com>2015-12-21 11:31:26 -0800
commit965a0eee46d24321f74c244e23c5a5f45e67e12b (patch)
treedf2d2693678a411330b56ada79255a0590b639d8
parent7ec9b5b98f6aea20f61185a71052a092b32e0706 (diff)
res_rtp_asterisk: Resolve further timing issues with DTLS negotiation
Resolves an edge case dtls negotiation delay for certain networks which somehow manage to drop the rtcp side's packet when these are both sent ast_rtp_remote_address_set, causing it to have to time-out and restart the handshake. Move dtls pending bio flush in to it's own function, and call it from ast_rtp_on_ice_complete, when we're rtp->ice, rather than when ast_rtp_remote_address_set. Keep the existing flush from the recent change to res_rtp_remote_address_set if ice is not being used. ASTERISK-25614 #close Reported-by: XenCALL Tested by: XenCALL Change-Id: Ie2caedbdee1783159f375589b6fd3845c8577ba5
-rw-r--r--res/res_rtp_asterisk.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 3dfaf87fa..db676f4b7 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -444,6 +444,7 @@ 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_flush_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp);
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
@@ -1683,15 +1684,20 @@ static void ast_rtp_on_ice_complete(pj_ice_sess *ice, pj_status_t status)
if (rtp->rtcp) {
update_address_with_ice_candidate(rtp, AST_RTP_ICE_COMPONENT_RTCP, &rtp->rtcp->them);
}
- }
#ifdef HAVE_OPENSSL_SRTP
- dtls_perform_handshake(instance, &rtp->dtls, 0);
+ if (rtp->dtls.dtls_setup != AST_RTP_DTLS_SETUP_PASSIVE) {
+ dtls_perform_handshake(instance, &rtp->dtls, 0);
+ }
+ else {
+ dtls_srtp_flush_pending(instance, rtp); /* this flushes pending BIO for both rtp & rtcp as needed. */
+ }
- if (rtp->rtcp) {
- dtls_perform_handshake(instance, &rtp->rtcp->dtls, 1);
- }
+ if (rtp->rtcp && rtp->rtcp->dtls.dtls_setup != AST_RTP_DTLS_SETUP_PASSIVE) {
+ dtls_perform_handshake(instance, &rtp->rtcp->dtls, 1);
+ }
#endif
+ }
if (!strictrtp) {
return;
@@ -1886,6 +1892,23 @@ static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, stru
AST_SCHED_DEL_UNREF(rtp->sched, dtls->timeout_timer, ao2_ref(instance, -1));
}
+static void dtls_srtp_flush_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
+{
+ struct dtls_details *dtls;
+
+ dtls = &rtp->dtls;
+ ast_mutex_lock(&dtls->lock);
+ dtls_srtp_check_pending(instance, rtp, 0);
+ ast_mutex_unlock(&dtls->lock);
+
+ if (rtp->rtcp) {
+ dtls = &rtp->rtcp->dtls;
+ ast_mutex_lock(&dtls->lock);
+ dtls_srtp_check_pending(instance, rtp, 1);
+ ast_mutex_unlock(&dtls->lock);
+ }
+}
+
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;
@@ -4822,9 +4845,6 @@ 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);
@@ -4845,22 +4865,10 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
#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.
+ * received in __rtp_recvfrom. If rtp->ice, this is instead done on_ice_complete
*/
- 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);
- }
+ if (!rtp->ice && rtp->dtls.dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+ dtls_srtp_flush_pending(instance, rtp);
}
#endif