From 1ed567a005a2a795c6279962bb6e7163ddfadfbd Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 8 Mar 2021 12:34:15 +0800 Subject: [PATCH] DTLS: Fix dead loop by duplicated Alert message --- trunk/src/app/srs_app_rtc_dtls.cpp | 30 +++++++++++++++++++++++------- trunk/src/app/srs_app_rtc_dtls.hpp | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_dtls.cpp b/trunk/src/app/srs_app_rtc_dtls.cpp index d2d6bc364..0d813132c 100644 --- a/trunk/src/app/srs_app_rtc_dtls.cpp +++ b/trunk/src/app/srs_app_rtc_dtls.cpp @@ -471,17 +471,33 @@ srs_error_t SrsDtlsImpl::do_on_dtls(char* data, int nb_data) return srs_error_wrap(err, "do handshake"); } - while (BIO_ctrl_pending(bio_in) > 0) { + // If there is data in bio_in, read it to let SSL consume it. + // @remark Limit the max loop, to avoid the dead loop. + for (int i = 0; i < 1024 && BIO_ctrl_pending(bio_in) > 0; i++) { char buf[8092]; - int nb = SSL_read(dtls, buf, sizeof(buf)); - if (nb <= 0) { + int r0 = SSL_read(dtls, buf, sizeof(buf)); + int r1 = SSL_get_error(dtls, r0); + + if (r0 <= 0) { + // SSL_ERROR_ZERO_RETURN + // + // The TLS/SSL connection has been closed. If the protocol version is SSL 3.0 or higher, + // this result code is returned only if a closure alert has occurred in the protocol, + // i.e. if the connection has been closed cleanly. + // @see https://www.openssl.org/docs/man1.1.0/man3/SSL_get_error.html + // @remark Already close, never read again, because padding always exsists. + if (r1 != SSL_ERROR_WANT_READ && r1 != SSL_ERROR_WANT_WRITE) { + break; + } continue; } - srs_trace("DTLS: read nb=%d, data=[%s]", nb, srs_string_dumps_hex(buf, nb, 32).c_str()); - if ((err = callback_->on_dtls_application_data(buf, nb)) != srs_success) { - return srs_error_wrap(err, "on DTLS data, size=%u, data=[%s]", nb, - srs_string_dumps_hex(buf, nb, 32).c_str()); + srs_trace("DTLS: read r0=%d, r1=%d, padding=%d, done=%d, data=[%s]", + r0, r1, BIO_ctrl_pending(bio_in), handshake_done_for_us, srs_string_dumps_hex(buf, r0, 32).c_str()); + + if ((err = callback_->on_dtls_application_data(buf, r0)) != srs_success) { + return srs_error_wrap(err, "on DTLS data, done=%d, r1=%d, size=%u, data=[%s]", handshake_done_for_us, + r1, r0, srs_string_dumps_hex(buf, r0, 32).c_str()); } } diff --git a/trunk/src/app/srs_app_rtc_dtls.hpp b/trunk/src/app/srs_app_rtc_dtls.hpp index 75e099f83..f72f6ef0d 100644 --- a/trunk/src/app/srs_app_rtc_dtls.hpp +++ b/trunk/src/app/srs_app_rtc_dtls.hpp @@ -118,7 +118,7 @@ protected: // @remark: dtls_version_ default value is SrsDtlsVersionAuto. SrsDtlsVersion version_; protected: - // Whether the handhshake is done, for us only. + // Whether the handshake is done, for us only. // @remark For us only, means peer maybe not done, we also need to handle the DTLS packet. bool handshake_done_for_us; // DTLS packet cache, only last out-going packet.