tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mnetwerk/sctp/datachannel/DataChannel.cpp | 26+++++++++++++++++++++-----
Mnetwerk/sctp/datachannel/DataChannel.h | 2+-
Mnetwerk/sctp/datachannel/DataChannelDcSctp.cpp | 8+++++---
Mnetwerk/sctp/datachannel/DataChannelDcSctp.h | 2+-
Mnetwerk/sctp/datachannel/DataChannelUsrsctp.cpp | 5+++--
Mnetwerk/sctp/datachannel/DataChannelUsrsctp.h | 2+-
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