Description: Add support for DTLS retransmission Author: NITESH BANSAL --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -301,6 +301,7 @@ unsigned int dtls_failure:1; /*!< Failure occurred during DTLS negotiation */ 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 */ #endif }; @@ -1588,6 +1589,31 @@ /* We just use the verify_callback to request a certificate from the client */ return 1; } + +static int dtls_srtp_handle_timeout(const void *data) +{ + struct ast_rtp_instance *instance = (struct ast_rtp_instance *)data; + struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); + + rtp->dtlstimerid = -1; + + if (rtp && rtp->ssl) + { + DTLSv1_handle_timeout(rtp->ssl); + } + + if (rtp->rtcp && rtp->rtcp->ssl) + { + DTLSv1_handle_timeout(rtp->rtcp->ssl); + } + + dtls_srtp_check_pending(instance, rtp); + + ao2_ref(instance, -1); + + return 0; +} + /*SRTP_DTLS */ static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp) { @@ -1595,6 +1621,7 @@ if (rtp->ssl) { size_t pending = BIO_ctrl_pending(rtp->write_bio); + struct timeval dtls_timeout; /* timeout on DTLS */ if (pending > 0) { char outgoing[pending]; @@ -1623,6 +1650,24 @@ } /*SRTP_DTLS */ + /* Stop existing DTLS timer if running */ + if (rtp->dtlstimerid > -1) + { + AST_SCHED_DEL_UNREF(rtp->sched, rtp->dtlstimerid, ao2_ref(instance, -1)); + rtp->dtlstimerid = -1; + } + + if (DTLSv1_get_timeout(rtp->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); + } + } + __rtp_sendto(instance, outgoing, out, 0, &remote_address, 0, &ice, 0); /*SRTP_DTLS */ if(dtlsdebug) @@ -1689,6 +1734,7 @@ return 0; } + static int dtls_srtp_setup(struct ast_rtp *rtp, struct ast_srtp *srtp, struct ast_rtp_instance *instance) { unsigned char material[SRTP_MASTER_LEN * 2]; @@ -2374,6 +2420,7 @@ #ifdef HAVE_OPENSSL_SRTP rtp->rekeyid = -1; + rtp->dtlstimerid = -1; rtp->local_fingerprint_type = AST_RTP_DTLS_HASH_NONE; rtp->remote_fingerprint_type = AST_RTP_DTLS_HASH_NONE; @@ -4738,6 +4785,7 @@ #ifdef HAVE_OPENSSL_SRTP AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1)); + AST_SCHED_DEL_UNREF(rtp->sched, rtp->dtlstimerid, ao2_ref(instance, -1)); #endif if (rtp->rtcp && rtp->rtcp->schedid > 0) {