1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

RTC: Refine DTLS ARQ, use step interval

This commit is contained in:
winlin 2020-10-03 21:34:34 +08:00
parent e61391028e
commit ba6462aab4
5 changed files with 48 additions and 31 deletions

View file

@ -36,6 +36,7 @@
#define TAG_MAIN "MAIN" #define TAG_MAIN "MAIN"
#define TAG_MAYBE "MAYBE" #define TAG_MAYBE "MAYBE"
#define TAG_DTLS_ALERT "DTLS_ALERT" #define TAG_DTLS_ALERT "DTLS_ALERT"
#define TAG_DTLS_HANG "DTLS_HANG"
#define TAG_RESOURCE_UNSUB "RESOURCE_UNSUB" #define TAG_RESOURCE_UNSUB "RESOURCE_UNSUB"
// Use memory/disk cache and donot flush when write log. // Use memory/disk cache and donot flush when write log.

View file

@ -378,12 +378,18 @@ SrsDtlsImpl::SrsDtlsImpl(ISrsDtlsCallback* callback)
last_outgoing_packet_cache = new uint8_t[kRtpPacketSize]; last_outgoing_packet_cache = new uint8_t[kRtpPacketSize];
nn_last_outgoing_packet = 0; nn_last_outgoing_packet = 0;
nn_arq_packets = 0;
version_ = SrsDtlsVersionAuto; version_ = SrsDtlsVersionAuto;
} }
SrsDtlsImpl::~SrsDtlsImpl() SrsDtlsImpl::~SrsDtlsImpl()
{ {
if (!handshake_done_for_us) {
srs_warn2(TAG_DTLS_HANG, "DTLS: Hang, done=%u, version=%d, arq=%u", handshake_done_for_us,
version_, nn_arq_packets);
}
if (dtls_ctx) { if (dtls_ctx) {
SSL_CTX_free(dtls_ctx); SSL_CTX_free(dtls_ctx);
dtls_ctx = NULL; dtls_ctx = NULL;
@ -557,9 +563,9 @@ void SrsDtlsImpl::state_trace(uint8_t* data, int length, bool incoming, int r0,
handshake_type = (uint8_t)data[13]; handshake_type = (uint8_t)data[13];
} }
srs_trace("DTLS: %s %s, done=%u, cache=%u, arq=%u, r0=%d, r1=%d, len=%u, cnt=%u, size=%u, hs=%u", srs_trace("DTLS: %s %s, done=%u, cache=%u, arq=%u/%u, r0=%d, r1=%d, len=%u, cnt=%u, size=%u, hs=%u",
(is_dtls_client()? "Active":"Passive"), (incoming? "RECV":"SEND"), handshake_done_for_us, cache, arq, (is_dtls_client()? "Active":"Passive"), (incoming? "RECV":"SEND"), handshake_done_for_us, cache, arq,
r0, r1, length, content_type, size, handshake_type); nn_arq_packets, r0, r1, length, content_type, size, handshake_type);
} }
const int SRTP_MASTER_KEY_KEY_LEN = 16; const int SRTP_MASTER_KEY_KEY_LEN = 16;
@ -608,8 +614,16 @@ SrsDtlsClientImpl::SrsDtlsClientImpl(ISrsDtlsCallback* callback) : SrsDtlsImpl(c
{ {
trd = NULL; trd = NULL;
state_ = SrsDtlsStateInit; state_ = SrsDtlsStateInit;
arq_first = 50 * SRS_UTIME_MILLISECONDS;
arq_interval = 100 * SRS_UTIME_MILLISECONDS; // The first wait and base interval for ARQ.
arq_interval = 10 * SRS_UTIME_MILLISECONDS;
// Use step timeout for ARQ, the total timeout is sum(arq_to_ratios)*arq_interval.
// for example, if arq_interval is 10ms, arq_to_ratios is [3, 6, 9, 15, 20, 40, 80, 160],
// then total timeout is sum([3, 6, 9, 15, 20, 40, 80, 160]) * 10ms = 3330ms.
int ratios[] = {3, 6, 9, 15, 20, 40, 80, 160};
srs_assert(sizeof(arq_to_ratios) == sizeof(ratios));
memcpy(arq_to_ratios, ratios, sizeof(ratios));
} }
SrsDtlsClientImpl::~SrsDtlsClientImpl() SrsDtlsClientImpl::~SrsDtlsClientImpl()
@ -742,12 +756,10 @@ srs_error_t SrsDtlsClientImpl::cycle()
{ {
srs_error_t err = srs_success; srs_error_t err = srs_success;
// The first ARQ delay.
srs_usleep(arq_first);
// Limit the max retry for ARQ. // Limit the max retry for ARQ.
for (int arq_retry_left = 7; arq_retry_left > 0; arq_retry_left--) { for (int i = 0; i < sizeof(arq_to_ratios) / sizeof(int); i++) {
srs_info("arq cycle, state=%u, retry=%d", state_, arq_retry_left); srs_utime_t arq_to = arq_interval * arq_to_ratios[i];
srs_usleep(arq_to);
// We ignore any error for ARQ thread. // We ignore any error for ARQ thread.
if ((err = trd->pull()) != srs_success) { if ((err = trd->pull()) != srs_success) {
@ -772,6 +784,7 @@ srs_error_t SrsDtlsClientImpl::cycle()
if (size) { if (size) {
// Trace the detail of DTLS packet. // Trace the detail of DTLS packet.
state_trace((uint8_t*)data, size, false, 1, SSL_ERROR_NONE, true, true); state_trace((uint8_t*)data, size, false, 1, SSL_ERROR_NONE, true, true);
nn_arq_packets++;
if ((err = callback_->write_dtls_data(data, size)) != srs_success) { if ((err = callback_->write_dtls_data(data, size)) != srs_success) {
return srs_error_wrap(err, "dtls send size=%u, data=[%s]", size, return srs_error_wrap(err, "dtls send size=%u, data=[%s]", size,
@ -779,8 +792,8 @@ srs_error_t SrsDtlsClientImpl::cycle()
} }
} }
// TODO: Use ARQ step timeouts. srs_info("arq cycle, done=%u, state=%u, retry=%d, interval=%dms, to=%dms, size=%d, nn=%d", handshake_done_for_us,
srs_usleep(arq_interval); state_, i, srsu2msi(arq_interval), srsu2msi(arq_to), size, nn_arq_packets);
} }
return err; return err;
@ -820,6 +833,7 @@ void SrsDtlsServerImpl::on_ssl_out_data(uint8_t*& data, int& size, bool& cached)
if (size <= 0 && nn_last_outgoing_packet) { if (size <= 0 && nn_last_outgoing_packet) {
size = nn_last_outgoing_packet; size = nn_last_outgoing_packet;
data = last_outgoing_packet_cache; data = last_outgoing_packet_cache;
nn_arq_packets++;
cached = true; cached = true;
} }
} }

View file

@ -124,6 +124,8 @@ protected:
// DTLS packet cache, only last out-going packet. // DTLS packet cache, only last out-going packet.
uint8_t* last_outgoing_packet_cache; uint8_t* last_outgoing_packet_cache;
int nn_last_outgoing_packet; int nn_last_outgoing_packet;
// The stat for ARQ packets.
int nn_arq_packets;
public: public:
SrsDtlsImpl(ISrsDtlsCallback* callback); SrsDtlsImpl(ISrsDtlsCallback* callback);
virtual ~SrsDtlsImpl(); virtual ~SrsDtlsImpl();
@ -154,8 +156,8 @@ private:
// The DTLS-client state to drive the ARQ thread. // The DTLS-client state to drive the ARQ thread.
SrsDtlsState state_; SrsDtlsState state_;
// The timeout for ARQ. // The timeout for ARQ.
srs_utime_t arq_first;
srs_utime_t arq_interval; srs_utime_t arq_interval;
int arq_to_ratios[8];
public: public:
SrsDtlsClientImpl(ISrsDtlsCallback* callback); SrsDtlsClientImpl(ISrsDtlsCallback* callback);
virtual ~SrsDtlsClientImpl(); virtual ~SrsDtlsClientImpl();

View file

@ -77,7 +77,7 @@ extern srs_utime_t _srs_tmp_timeout;
// For init array data. // For init array data.
#define HELPER_ARRAY_INIT(buf, sz, val) \ #define HELPER_ARRAY_INIT(buf, sz, val) \
memset(buf, val, sz) for (int _iii = 0; _iii < sz; _iii++) (buf)[_iii] = val
// Dump simple stream to string. // Dump simple stream to string.
#define HELPER_BUFFER2STR(io) \ #define HELPER_BUFFER2STR(io) \

View file

@ -856,10 +856,10 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 10 packets, total packets should be 8(max to 8). // Lost 10 packets, total packets should be 9(max to 9).
// Note that only one server hello. // Note that only one server hello.
cio.nn_client_hello_lost = 10; cio.nn_client_hello_lost = 10;
@ -872,7 +872,7 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
EXPECT_FALSE(cio.done); EXPECT_FALSE(cio.done);
EXPECT_FALSE(sio.done); EXPECT_FALSE(sio.done);
EXPECT_EQ(8, cio.nn_client_hello); EXPECT_EQ(9, cio.nn_client_hello);
EXPECT_EQ(0, sio.nn_server_hello); EXPECT_EQ(0, sio.nn_server_hello);
EXPECT_EQ(0, cio.nn_certificate); EXPECT_EQ(0, cio.nn_certificate);
EXPECT_EQ(0, sio.nn_new_session); EXPECT_EQ(0, sio.nn_new_session);
@ -888,10 +888,10 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 10 packets, total packets should be 8(max to 8). // Lost 10 packets, total packets should be 9(max to 9).
// Note that only one server NewSessionTicket. // Note that only one server NewSessionTicket.
cio.nn_certificate_lost = 10; cio.nn_certificate_lost = 10;
@ -906,7 +906,7 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
EXPECT_EQ(1, cio.nn_client_hello); EXPECT_EQ(1, cio.nn_client_hello);
EXPECT_EQ(1, sio.nn_server_hello); EXPECT_EQ(1, sio.nn_server_hello);
EXPECT_EQ(8, cio.nn_certificate); EXPECT_EQ(9, cio.nn_certificate);
EXPECT_EQ(0, sio.nn_new_session); EXPECT_EQ(0, sio.nn_new_session);
EXPECT_EQ(0, sio.nn_change_cipher); EXPECT_EQ(0, sio.nn_change_cipher);
} }
@ -920,10 +920,10 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 10 packets, total packets should be 8(max to 8). // Lost 10 packets, total packets should be 9(max to 9).
sio.nn_server_hello_lost = 10; sio.nn_server_hello_lost = 10;
HELPER_EXPECT_SUCCESS(client.start_active_handshake()); HELPER_EXPECT_SUCCESS(client.start_active_handshake());
@ -935,8 +935,8 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
EXPECT_FALSE(cio.done); EXPECT_FALSE(cio.done);
EXPECT_FALSE(sio.done); EXPECT_FALSE(sio.done);
EXPECT_EQ(8, cio.nn_client_hello); EXPECT_EQ(9, cio.nn_client_hello);
EXPECT_EQ(8, sio.nn_server_hello); EXPECT_EQ(9, sio.nn_server_hello);
EXPECT_EQ(0, cio.nn_certificate); EXPECT_EQ(0, cio.nn_certificate);
EXPECT_EQ(0, sio.nn_new_session); EXPECT_EQ(0, sio.nn_new_session);
EXPECT_EQ(0, sio.nn_change_cipher); EXPECT_EQ(0, sio.nn_change_cipher);
@ -951,10 +951,10 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 10 packets, total packets should be 8(max to 8). // Lost 10 packets, total packets should be 9(max to 9).
sio.nn_new_session_lost = 10; sio.nn_new_session_lost = 10;
HELPER_EXPECT_SUCCESS(client.start_active_handshake()); HELPER_EXPECT_SUCCESS(client.start_active_handshake());
@ -969,8 +969,8 @@ VOID TEST(KernelRTCTest, DTLSARQLimitTest)
EXPECT_EQ(1, cio.nn_client_hello); EXPECT_EQ(1, cio.nn_client_hello);
EXPECT_EQ(1, sio.nn_server_hello); EXPECT_EQ(1, sio.nn_server_hello);
EXPECT_EQ(8, cio.nn_certificate); EXPECT_EQ(9, cio.nn_certificate);
EXPECT_EQ(8, sio.nn_new_session); EXPECT_EQ(9, sio.nn_new_session);
EXPECT_EQ(0, sio.nn_change_cipher); EXPECT_EQ(0, sio.nn_change_cipher);
} }
} }
@ -1012,8 +1012,8 @@ VOID TEST(KernelRTCTest, DTLSClientARQTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 2 packets, total packets should be 3. // Lost 2 packets, total packets should be 3.
// Note that only one server hello. // Note that only one server hello.
@ -1044,8 +1044,8 @@ VOID TEST(KernelRTCTest, DTLSClientARQTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 2 packets, total packets should be 3. // Lost 2 packets, total packets should be 3.
// Note that only one server NewSessionTicket. // Note that only one server NewSessionTicket.
@ -1105,8 +1105,8 @@ VOID TEST(KernelRTCTest, DTLSServerARQTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 2 packets, total packets should be 3. // Lost 2 packets, total packets should be 3.
sio.nn_server_hello_lost = 2; sio.nn_server_hello_lost = 2;
@ -1136,8 +1136,8 @@ VOID TEST(KernelRTCTest, DTLSServerARQTest)
HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0")); HELPER_EXPECT_SUCCESS(server.initialize("passive", "dtls1.0"));
// Use very short interval for utest. // Use very short interval for utest.
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_first = 1 * SRS_UTIME_MILLISECONDS;
dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS; dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_interval = 1 * SRS_UTIME_MILLISECONDS;
HELPER_ARRAY_INIT(dynamic_cast<SrsDtlsClientImpl*>(client.impl)->arq_to_ratios, 8, 1);
// Lost 2 packets, total packets should be 3. // Lost 2 packets, total packets should be 3.
sio.nn_new_session_lost = 2; sio.nn_new_session_lost = 2;