commit f6fd8610b5e399c38d47188a330d008907e3920e
parent c8fc75101bdc7b52d894d7ccc895080e3ee5208e
Author: Byron Campen <docfaraday@gmail.com>
Date: Wed, 29 Oct 2025 12:35:16 +0000
Bug 1988096: Make ResetStreams fallible. r=ng
Differential Revision: https://phabricator.services.mozilla.com/D269066
Diffstat:
6 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -1177,11 +1177,27 @@ void DataChannelConnection::EndOfStream(DataChannel* aChannel) {
if (channel->mSendStreamNeedsReset) {
DC_INFO(("%p: Need to send a reset, closing gracefully", this));
nsTArray<uint16_t> temp({stream});
- ResetStreams(temp);
- } else if (!channel->mRecvStreamNeedsReset) {
- // Stream is reset in both directions (or never existed in the first
- // place), we're ready to finish tearing down.
- DC_INFO(("%p: Stream does not need reset in either direction", this));
+ bool success = ResetStreams(temp);
+ if (success) {
+ return;
+ }
+ // We presume that OnStreamResetComplete will not be called in
+ // this case, nor will we receive a stream reset from the other
+ // end.
+ DC_INFO(
+ ("%p: Failed to send a reset for channel %p, closing "
+ "immediately",
+ this, channel.get()));
+ channel->mRecvStreamNeedsReset = false;
+ }
+
+ if (!channel->mRecvStreamNeedsReset) {
+ // Stream is reset in both directions (or never existed in the
+ // first place), we're ready to finish tearing down.
+ DC_INFO(
+ ("%p: Stream does not need reset in either direction for "
+ "channel %p",
+ this, channel.get()));
FinishClose_s(channel);
}
}));
diff --git a/netwerk/sctp/datachannel/DataChannel.h b/netwerk/sctp/datachannel/DataChannel.h
@@ -198,7 +198,7 @@ class DataChannelConnection : public net::NeckoTargetHolder {
// Called when the base class receives a packet from the transport
virtual void OnSctpPacketReceived(const MediaPacket& packet) = 0;
// Called when the base class is closing streams
- virtual void ResetStreams(nsTArray<uint16_t>& aStreams) = 0;
+ virtual bool ResetStreams(nsTArray<uint16_t>& aStreams) = 0;
// Called when the SCTP connection is being shut down
virtual void Destroy();
diff --git a/netwerk/sctp/datachannel/DataChannelDcSctp.cpp b/netwerk/sctp/datachannel/DataChannelDcSctp.cpp
@@ -152,19 +152,21 @@ void DataChannelConnectionDcSctp::OnSctpPacketReceived(
mDcSctp->ReceivePacket(data);
}
-void DataChannelConnectionDcSctp::ResetStreams(nsTArray<uint16_t>& aStreams) {
+bool DataChannelConnectionDcSctp::ResetStreams(nsTArray<uint16_t>& aStreams) {
MOZ_ASSERT(mSTS->IsOnCurrentThread());
DC_DEBUG(("%s: %p", __func__, this));
if (!mDcSctp) {
- return;
+ return false;
}
std::vector<StreamID> converted;
for (auto id : aStreams) {
DC_DEBUG(("%s: %p Resetting %u", __func__, this, id));
converted.push_back(StreamID(id));
}
- mDcSctp->ResetStreams(webrtc::ArrayView<const StreamID>(converted));
+ auto result =
+ mDcSctp->ResetStreams(webrtc::ArrayView<const StreamID>(converted));
aStreams.Clear();
+ return result == ResetStreamsStatus::kPerformed;
}
void DataChannelConnectionDcSctp::OnStreamOpen(uint16_t aStream) {
diff --git a/netwerk/sctp/datachannel/DataChannelDcSctp.h b/netwerk/sctp/datachannel/DataChannelDcSctp.h
@@ -28,7 +28,7 @@ class DataChannelConnectionDcSctp : public DataChannelConnection,
bool Init(const uint16_t aLocalPort, const uint16_t aNumStreams) override;
int SendMessage(DataChannel& aChannel, OutgoingMsg&& aMsg) override;
void OnSctpPacketReceived(const MediaPacket& aPacket) override;
- void ResetStreams(nsTArray<uint16_t>& aStreams) override;
+ bool ResetStreams(nsTArray<uint16_t>& aStreams) override;
// This is called after an ACK comes in, to prompt subclasses to deliver
// anything they've buffered while awaiting the ACK.
void OnStreamOpen(uint16_t aStream) override;
diff --git a/netwerk/sctp/datachannel/DataChannelUsrsctp.cpp b/netwerk/sctp/datachannel/DataChannelUsrsctp.cpp
@@ -1213,14 +1213,14 @@ void DataChannelConnectionUsrsctp::HandleSendFailedEvent(
}
}
-void DataChannelConnectionUsrsctp::ResetStreams(nsTArray<uint16_t>& aStreams) {
+bool DataChannelConnectionUsrsctp::ResetStreams(nsTArray<uint16_t>& aStreams) {
MOZ_ASSERT(mSTS->IsOnCurrentThread());
DC_DEBUG(("%s %p: Sending outgoing stream reset for %zu streams", __func__,
this, aStreams.Length()));
if (aStreams.IsEmpty()) {
DC_DEBUG(("No streams to reset"));
- return;
+ return false;
}
const size_t len =
sizeof(sctp_reset_streams) + (aStreams.Length()) * sizeof(uint16_t);
@@ -1244,6 +1244,7 @@ void DataChannelConnectionUsrsctp::ResetStreams(nsTArray<uint16_t>& aStreams) {
aStreams.Clear();
}
free(srs);
+ return aStreams.Length() == 0;
}
void DataChannelConnectionUsrsctp::HandleStreamResetEvent(
diff --git a/netwerk/sctp/datachannel/DataChannelUsrsctp.h b/netwerk/sctp/datachannel/DataChannelUsrsctp.h
@@ -52,7 +52,7 @@ class DataChannelConnectionUsrsctp : public DataChannelConnection {
bool Init(const uint16_t aLocalPort, const uint16_t aNumStreams) override;
int SendMessage(DataChannel& aChannel, OutgoingMsg&& aMsg) override;
void OnSctpPacketReceived(const MediaPacket& packet) override;
- void ResetStreams(nsTArray<uint16_t>& aStreams) override;
+ bool ResetStreams(nsTArray<uint16_t>& aStreams) override;
void OnStreamOpen(uint16_t stream) override;
// Called on data reception from the SCTP library