Add test for many non-dropped packets in unreliable mode.
These tests document existing behavior; there are notes about where
this behavior is either surprising or wrong.
Bug: chromium:1148951
Change-Id: If9875fb744c44c129ff9949d1bab3d3d99f17b81
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/217520
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34058}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 3039ec6..82f90df 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -1056,6 +1056,7 @@
"../rtc_base/synchronization:mutex",
"../rtc_base/third_party/base64",
"../rtc_base/third_party/sigslot",
+ "../system_wrappers:field_trial",
"../system_wrappers:metrics",
"../test:field_trial",
"../test:fileutils",
diff --git a/pc/data_channel_integrationtest.cc b/pc/data_channel_integrationtest.cc
index 4b6ae1f..1deeb55 100644
--- a/pc/data_channel_integrationtest.cc
+++ b/pc/data_channel_integrationtest.cc
@@ -27,6 +27,7 @@
#include "rtc_base/gunit.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/virtual_socket_server.h"
+#include "system_wrappers/include/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
@@ -622,7 +623,7 @@
kDefaultTimeout);
}
-TEST_P(DataChannelIntegrationTest, QueuedPacketsGetDeliveredInUnReliableMode) {
+TEST_P(DataChannelIntegrationTest, QueuedPacketsGetDroppedInUnreliableMode) {
CreatePeerConnectionWrappers();
ConnectFakeSignaling();
DataChannelInit init;
@@ -637,6 +638,9 @@
kDefaultTimeout);
// Cause a temporary network outage
virtual_socket_server()->set_drop_probability(1.0);
+ // Send a few packets. Note that all get dropped only when all packets
+ // fit into the receiver receive window/congestion window, so that they
+ // actually get sent.
for (int i = 1; i <= 10; i++) {
caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
}
@@ -659,6 +663,116 @@
EXPECT_EQ(2u, callee()->data_observer()->received_message_count());
}
+TEST_P(DataChannelIntegrationTest,
+ QueuedPacketsGetDroppedInLifetimeLimitedMode) {
+ CreatePeerConnectionWrappers();
+ ConnectFakeSignaling();
+ DataChannelInit init;
+ init.maxRetransmitTime = 1;
+ init.ordered = false;
+ caller()->CreateDataChannel(&init);
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+ ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
+ caller()->data_channel()->Send(DataBuffer("hello first"));
+ ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
+ kDefaultTimeout);
+ // Cause a temporary network outage
+ virtual_socket_server()->set_drop_probability(1.0);
+ for (int i = 1; i <= 200; i++) {
+ caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
+ }
+ // Nothing should be delivered during outage.
+ // We do a short wait to verify that delivery count is still 1,
+ // and to make sure max packet lifetime (which is in ms) is exceeded.
+ WAIT(false, 10);
+ EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
+ // Reverse the network outage.
+ virtual_socket_server()->set_drop_probability(0.0);
+ // Send a new packet, and wait for it to be delivered.
+ caller()->data_channel()->Send(DataBuffer("After block"));
+ EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
+ kDefaultTimeout);
+ // Some messages should be lost, but first and last message should have
+ // been delivered.
+ // First, check that the protocol guarantee is preserved.
+ EXPECT_GT(202u, callee()->data_observer()->received_message_count());
+ EXPECT_LE(2u, callee()->data_observer()->received_message_count());
+ // Then, check that observed behavior (lose some messages) has not changed
+ if (webrtc::field_trial::IsEnabled("WebRTC-DataChannel-Dcsctp")) {
+ // DcSctp loses all messages. This is correct.
+ EXPECT_EQ(2u, callee()->data_observer()->received_message_count());
+ } else {
+ // Usrsctp loses some messages, but keeps messages not attempted.
+ // THIS IS THE WRONG BEHAVIOR. According to discussion in
+ // https://github.com/sctplab/usrsctp/issues/584, all these packets
+ // should be discarded.
+ // TODO(bugs.webrtc.org/12731): Fix this.
+ EXPECT_EQ(90u, callee()->data_observer()->received_message_count());
+ }
+}
+
+TEST_P(DataChannelIntegrationTest,
+ SomeQueuedPacketsGetDroppedInMaxRetransmitsMode) {
+ CreatePeerConnectionWrappers();
+ ConnectFakeSignaling();
+ DataChannelInit init;
+ init.maxRetransmits = 0;
+ init.ordered = false;
+ caller()->CreateDataChannel(&init);
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+ ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
+ caller()->data_channel()->Send(DataBuffer("hello first"));
+ ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
+ kDefaultTimeout);
+ // Cause a temporary network outage
+ virtual_socket_server()->set_drop_probability(1.0);
+ // Fill the buffer until queued data starts to build
+ size_t packet_counter = 0;
+ while (caller()->data_channel()->buffered_amount() < 1 &&
+ packet_counter < 10000) {
+ packet_counter++;
+ caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
+ }
+ if (caller()->data_channel()->buffered_amount()) {
+ RTC_LOG(LS_INFO) << "Buffered data after " << packet_counter << " packets";
+ } else {
+ RTC_LOG(LS_INFO) << "No buffered data after " << packet_counter
+ << " packets";
+ }
+ // Nothing should be delivered during outage.
+ // We do a short wait to verify that delivery count is still 1.
+ WAIT(false, 10);
+ EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
+ // Reverse the network outage.
+ virtual_socket_server()->set_drop_probability(0.0);
+ // Send a new packet, and wait for it to be delivered.
+ caller()->data_channel()->Send(DataBuffer("After block"));
+ EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
+ kDefaultTimeout);
+ // Some messages should be lost, but first and last message should have
+ // been delivered.
+ // Due to the fact that retransmissions are only counted when the packet
+ // goes on the wire, NOT when they are stalled in queue due to
+ // congestion, we expect some of the packets to be delivered, because
+ // congestion prevented them from being sent.
+ // Citation: https://tools.ietf.org/html/rfc7496#section-3.1
+
+ // First, check that the protocol guarantee is preserved.
+ EXPECT_GT(packet_counter,
+ callee()->data_observer()->received_message_count());
+ EXPECT_LE(2u, callee()->data_observer()->received_message_count());
+ // Then, check that observed behavior (lose between 100 and 200 messages)
+ // has not changed.
+ // Usrsctp behavior is different on Android (177) and other platforms (122).
+ // Dcsctp loses 432 packets.
+ EXPECT_GT(2 + packet_counter - 100,
+ callee()->data_observer()->received_message_count());
+ EXPECT_LT(2 + packet_counter - 500,
+ callee()->data_observer()->received_message_count());
+}
+
INSTANTIATE_TEST_SUITE_P(
DataChannelIntegrationTest,
DataChannelIntegrationTest,
diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc
index 89b39e5..81a4cd8 100644
--- a/pc/peer_connection_factory.cc
+++ b/pc/peer_connection_factory.cc
@@ -139,6 +139,7 @@
case cricket::MEDIA_TYPE_UNSUPPORTED:
return RtpCapabilities();
}
+ RTC_DLOG(LS_ERROR) << "Got unexpected MediaType " << kind;
RTC_CHECK_NOTREACHED();
}
@@ -165,6 +166,7 @@
case cricket::MEDIA_TYPE_UNSUPPORTED:
return RtpCapabilities();
}
+ RTC_DLOG(LS_ERROR) << "Got unexpected MediaType " << kind;
RTC_CHECK_NOTREACHED();
}