From 6317abb58bbe58c95b64654cee686ea0ab461776 Mon Sep 17 00:00:00 2001 From: Aaro Altonen Date: Thu, 1 Oct 2020 11:07:54 +0300 Subject: [PATCH] Set ZRTP timeout properly on both platforms --- include/zrtp.hh | 8 ------ include/zrtp/zrtp_receiver.hh | 2 +- src/zrtp.cc | 48 ++++++++--------------------------- src/zrtp/zrtp_receiver.cc | 15 +++++++++-- 4 files changed, 25 insertions(+), 48 deletions(-) diff --git a/include/zrtp.hh b/include/zrtp.hh index 174a2a4..1581fba 100644 --- a/include/zrtp.hh +++ b/include/zrtp.hh @@ -207,14 +207,6 @@ namespace uvg_rtp { * Return RTP_TIMEOUT if remote did not send messages in timely manner */ rtp_error_t init_msm(uint32_t ssrc, uvg_rtp::socket *socket, sockaddr_in& addr); - /* Set timeout for a socket, needed by backoff timers of ZRTP - * - * "timeout" tells the timeout in milliseconds - * - * Return RTP_OK on success - * Return RTP_GENERIC_ERROR if timeout could not be set */ - rtp_error_t set_timeout(size_t timeout); - /* Generate zid for this ZRTP instance. ZID is a unique, 96-bit long ID */ void generate_zid(); diff --git a/include/zrtp/zrtp_receiver.hh b/include/zrtp/zrtp_receiver.hh index bd78fe9..61d2a5f 100644 --- a/include/zrtp/zrtp_receiver.hh +++ b/include/zrtp/zrtp_receiver.hh @@ -16,7 +16,7 @@ namespace uvg_rtp { * Return -EPROTONOSUPPORT if message contains incompatible version number * Return -ENOPNOTSUPP if message type is not supported * Return -errno for any other error */ - int recv_msg(uvg_rtp::socket *socket, int flags); + int recv_msg(uvg_rtp::socket *socket, int timeout, int flags); /* TODO: */ ssize_t get_msg(void *ptr, size_t len); diff --git a/src/zrtp.cc b/src/zrtp.cc index 8718130..5342a03 100644 --- a/src/zrtp.cc +++ b/src/zrtp.cc @@ -51,23 +51,6 @@ uvg_rtp::zrtp::~zrtp() delete[] session_.l_msg.dh.second; } -/* "timeout" must be in milliseconds */ -rtp_error_t uvg_rtp::zrtp::set_timeout(size_t timeout) -{ - size_t msec = timeout % 1000; - size_t sec = timeout - msec; - - struct timeval tv = { - (int)sec / 1000, - (int)msec * 1000, - }; - - if (socket_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) != RTP_OK) - return RTP_GENERIC_ERROR; - - return RTP_OK; -} - void uvg_rtp::zrtp::generate_zid() { uvg_rtp::crypto::random::generate_random(session_.o_zid, 12); @@ -362,13 +345,11 @@ rtp_error_t uvg_rtp::zrtp::begin_session() int i = 0; for (i = 0; i < 20; ++i) { - set_timeout(rto); - if ((ret = hello.send_msg(socket_, addr_)) != RTP_OK) { LOG_ERROR("Failed to send Hello message"); } - if ((type = receiver_.recv_msg(socket_, 0)) > 0) { + if ((type = receiver_.recv_msg(socket_, rto, 0)) > 0) { /* We received something interesting, either Hello message from remote in which case * we need to send HelloACK message back and keep sending our Hello until HelloACK is received, * or HelloACK message which means we can stop sending our */ @@ -440,7 +421,7 @@ rtp_error_t uvg_rtp::zrtp::init_session(int key_agreement) /* First check if remote has already sent the message. * If so, they are the initiator and we're the responder */ - while ((type = receiver_.recv_msg(socket_, MSG_DONTWAIT)) != -RTP_INTERRUPTED) { + while ((type = receiver_.recv_msg(socket_, 0, MSG_DONTWAIT)) != -RTP_INTERRUPTED) { if (type == ZRTP_FT_COMMIT) { commit.parse_msg(receiver_, session_); session_.role = RESPONDER; @@ -455,13 +436,11 @@ rtp_error_t uvg_rtp::zrtp::init_session(int key_agreement) rto = 150; for (int i = 0; i < 10; ++i) { - set_timeout(rto); - if ((ret = commit.send_msg(socket_, addr_)) != RTP_OK) { LOG_ERROR("Failed to send Commit message!"); } - if ((type = receiver_.recv_msg(socket_, 0)) > 0) { + if ((type = receiver_.recv_msg(socket_, rto, 0)) > 0) { /* As per RFC 6189, if both parties have sent Commit message and the mode is DH, * hvi shall determine who is the initiator (the party with larger hvi is initiator) */ @@ -498,13 +477,11 @@ rtp_error_t uvg_rtp::zrtp::dh_part1() int type = 0; for (int i = 0; i < 10; ++i) { - set_timeout(rto); - if ((ret = dhpart.send_msg(socket_, addr_)) != RTP_OK) { LOG_ERROR("Failed to send DHPart1 Message!"); } - if ((type = receiver_.recv_msg(socket_, 0)) > 0) { + if ((type = receiver_.recv_msg(socket_, rto, 0)) > 0) { if (type == ZRTP_FT_DH_PART2) { if ((ret = dhpart.parse_msg(receiver_, session_)) != RTP_OK) { LOG_ERROR("Failed to parse DHPart2 Message!"); @@ -544,13 +521,11 @@ rtp_error_t uvg_rtp::zrtp::dh_part2() generate_shared_secrets_dh(); for (int i = 0; i < 10; ++i) { - set_timeout(rto); - if ((ret = dhpart.send_msg(socket_, addr_)) != RTP_OK) { LOG_ERROR("Failed to send DHPart2 Message!"); } - if ((type = receiver_.recv_msg(socket_, 0)) > 0) { + if ((type = receiver_.recv_msg(socket_, rto, 0)) > 0) { if (type == ZRTP_FT_CONFIRM1) { LOG_DEBUG("Confirm1 Message received"); return RTP_OK; @@ -573,13 +548,11 @@ rtp_error_t uvg_rtp::zrtp::responder_finalize_session() int type = 0; for (int i = 0; i < 10; ++i) { - set_timeout(rto); - if ((ret = confirm.send_msg(socket_, addr_)) != RTP_OK) { LOG_ERROR("Failed to send Confirm1 Message!"); } - if ((type = receiver_.recv_msg(socket_, 0)) > 0) { + if ((type = receiver_.recv_msg(socket_, rto, 0)) > 0) { if (type == ZRTP_FT_CONFIRM2) { if ((ret = confirm.parse_msg(receiver_, session_)) != RTP_OK) { LOG_ERROR("Failed to parse Confirm2 Message!"); @@ -622,13 +595,11 @@ rtp_error_t uvg_rtp::zrtp::initiator_finalize_session() } for (int i = 0; i < 10; ++i) { - set_timeout(rto); - if ((ret = confirm.send_msg(socket_, addr_)) != RTP_OK) { LOG_ERROR("Failed to send Confirm2 Message!"); } - if ((type = receiver_.recv_msg(socket_, 0)) > 0) { + if ((type = receiver_.recv_msg(socket_, rto, 0)) > 0) { if (type == ZRTP_FT_CONF2_ACK) { LOG_DEBUG("Conf2ACK received successfully!"); return RTP_OK; @@ -739,7 +710,10 @@ rtp_error_t uvg_rtp::zrtp::init_dhm(uint32_t ssrc, uvg_rtp::socket *socket, sock initialized_ = true; /* reset the timeout (no longer needed) */ - set_timeout(0); + struct timeval tv = { 0, 0 }; + + if (socket_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) != RTP_OK) + return RTP_GENERIC_ERROR; /* Session has been initialized successfully and SRTP can start */ return RTP_OK; diff --git a/src/zrtp/zrtp_receiver.cc b/src/zrtp/zrtp_receiver.cc index aa5e74d..920b29b 100644 --- a/src/zrtp/zrtp_receiver.cc +++ b/src/zrtp/zrtp_receiver.cc @@ -37,18 +37,29 @@ uvg_rtp::zrtp_msg::receiver::~receiver() delete[] mem_; } -int uvg_rtp::zrtp_msg::receiver::recv_msg(uvg_rtp::socket *socket, int flags) +int uvg_rtp::zrtp_msg::receiver::recv_msg(uvg_rtp::socket *socket, int timeout, int flags) { rtp_error_t ret = RTP_GENERIC_ERROR; int nread = 0; rlen_ = 0; #ifdef _WIN32 - if ((ret = uvg_rtp::poll::blocked_recv(socket, mem_, len_, 1000, &nread)) != RTP_OK) { + if ((ret = uvg_rtp::poll::blocked_recv(socket, mem_, len_, timeout, &nread)) != RTP_OK) { log_platform_error("blocked_recv() failed"); return ret; } #else + size_t msec = timeout % 1000; + size_t sec = timeout - msec; + + struct timeval tv = { + (int)sec / 1000, + (int)msec * 1000, + }; + + if (socket->setsockopt(SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)) != RTP_OK) + return RTP_GENERIC_ERROR; + if ((ret = socket->recv(mem_, len_, flags, &nread)) != RTP_OK) { if (ret == RTP_INTERRUPTED) return -ret;