dcsctp: Send buffered data directly on response
When a stream reset response has been received, this may result
in unpausing the streams (either because it was successful or
because it failed - but streams will be unpaused). Directly after
receiving the response, send out any pending chunks that are
ready to be sent.
Before this CL, they would eventually be sent out, but that is
unnecessary and undeterministic.
Bug: webrtc:14277
Change-Id: Ic1ab38bc3cea96cfec7419e25001f12807523a3a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/273800
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38009}
diff --git a/net/dcsctp/socket/dcsctp_socket.cc b/net/dcsctp/socket/dcsctp_socket.cc
index d77e591..f36e26d 100644
--- a/net/dcsctp/socket/dcsctp_socket.cc
+++ b/net/dcsctp/socket/dcsctp_socket.cc
@@ -1541,6 +1541,7 @@
void DcSctpSocket::HandleReconfig(
const CommonHeader& header,
const SctpPacket::ChunkDescriptor& descriptor) {
+ TimeMs now = callbacks_.TimeMillis();
absl::optional<ReConfigChunk> chunk = ReConfigChunk::Parse(descriptor.data);
if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
tcb_->stream_reset_handler().HandleReConfig(*std::move(chunk));
@@ -1549,6 +1550,9 @@
// that were waiting for this request to finish, continue resetting them.
MaybeSendResetStreamsRequest();
}
+ // If a response was processed, pending to-be-reset streams may now have
+ // become unpaused. Try to send more DATA chunks.
+ tcb_->SendBufferedPackets(now);
}
void DcSctpSocket::HandleShutdown(
diff --git a/net/dcsctp/socket/dcsctp_socket_test.cc b/net/dcsctp/socket/dcsctp_socket_test.cc
index 46ac4bd..f38624d 100644
--- a/net/dcsctp/socket/dcsctp_socket_test.cc
+++ b/net/dcsctp/socket/dcsctp_socket_test.cc
@@ -2815,5 +2815,39 @@
EXPECT_EQ(msg3->payload().size(), kSmallMessageSize);
}
+TEST(DcSctpSocketTest, ResetStreamsWithPausedSenderResumesWhenPerformed) {
+ SocketUnderTest a("A");
+ SocketUnderTest z("Z");
+
+ ConnectSockets(a, z);
+
+ a.socket.Send(DcSctpMessage(StreamID(1), PPID(51),
+ std::vector<uint8_t>(kSmallMessageSize)),
+ {});
+
+ a.socket.ResetStreams(std::vector<StreamID>({StreamID(1)}));
+
+ // Will be queued, as the stream has an outstanding reset operation.
+ a.socket.Send(DcSctpMessage(StreamID(1), PPID(52),
+ std::vector<uint8_t>(kSmallMessageSize)),
+ {});
+
+ EXPECT_CALL(a.cb, OnStreamsResetPerformed(ElementsAre(StreamID(1))));
+ EXPECT_CALL(z.cb, OnIncomingStreamsReset(ElementsAre(StreamID(1))));
+ ExchangeMessages(a, z);
+
+ absl::optional<DcSctpMessage> msg1 = z.cb.ConsumeReceivedMessage();
+ ASSERT_TRUE(msg1.has_value());
+ EXPECT_EQ(msg1->stream_id(), StreamID(1));
+ EXPECT_EQ(msg1->ppid(), PPID(51));
+ EXPECT_EQ(msg1->payload().size(), kSmallMessageSize);
+
+ absl::optional<DcSctpMessage> msg2 = z.cb.ConsumeReceivedMessage();
+ ASSERT_TRUE(msg2.has_value());
+ EXPECT_EQ(msg2->stream_id(), StreamID(1));
+ EXPECT_EQ(msg2->ppid(), PPID(52));
+ EXPECT_EQ(msg2->payload().size(), kSmallMessageSize);
+}
+
} // namespace
} // namespace dcsctp