Close data channels when ID assignment fails.
This prevents crashes due to unassigned IDs. Bug: chromium:945256 Change-Id: I63f3a17cc7dff07dab58a6bc59fe3606b23e8e18 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/129902 Reviewed-by: Seth Hampson <shampson@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27349}
This commit is contained in:
committed by
Commit Bot
parent
4c7112a27a
commit
1f928d3316
@ -147,6 +147,13 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
|
||||
virtual uint64_t bytes_received() const { return bytes_received_; }
|
||||
virtual bool Send(const DataBuffer& buffer);
|
||||
|
||||
// Close immediately, ignoring any queued data or closing procedure.
|
||||
// This is called for RTP data channels when SDP indicates a channel should
|
||||
// be removed, or SCTP data channels when the underlying SctpTransport is
|
||||
// being destroyed.
|
||||
// It is also called by the PeerConnection if SCTP ID assignment fails.
|
||||
void CloseAbruptly();
|
||||
|
||||
// Called when the channel's ready to use. That can happen when the
|
||||
// underlying DataMediaChannel becomes ready, or when this channel is a new
|
||||
// stream on an existing DataMediaChannel, and we've finished negotiation.
|
||||
@ -242,11 +249,6 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
|
||||
};
|
||||
|
||||
bool Init(const InternalDataChannelInit& config);
|
||||
// Close immediately, ignoring any queued data or closing procedure.
|
||||
// This is called for RTP data channels when SDP indicates a channel should
|
||||
// be removed, or SCTP data channels when the underlying SctpTransport is
|
||||
// being destroyed.
|
||||
void CloseAbruptly();
|
||||
void UpdateState();
|
||||
void SetState(DataState state);
|
||||
void DisconnectFromProvider();
|
||||
|
||||
@ -5102,16 +5102,23 @@ bool PeerConnection::HasDataChannels() const {
|
||||
}
|
||||
|
||||
void PeerConnection::AllocateSctpSids(rtc::SSLRole role) {
|
||||
std::vector<rtc::scoped_refptr<DataChannel>> channels_to_close;
|
||||
for (const auto& channel : sctp_data_channels_) {
|
||||
if (channel->id() < 0) {
|
||||
int sid;
|
||||
if (!sid_allocator_.AllocateSid(role, &sid)) {
|
||||
RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid.";
|
||||
RTC_LOG(LS_ERROR) << "Failed to allocate SCTP sid, closing channel.";
|
||||
channels_to_close.push_back(channel);
|
||||
continue;
|
||||
}
|
||||
channel->SetSctpSid(sid);
|
||||
}
|
||||
}
|
||||
// Since closing modifies the list of channels, we have to do the actual
|
||||
// closing outside the loop.
|
||||
for (const auto& channel : channels_to_close) {
|
||||
channel->CloseAbruptly();
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) {
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "api/audio_codecs/audio_encoder_factory_template.h"
|
||||
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
#include "media/sctp/sctp_transport_internal.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
@ -721,6 +722,29 @@ TEST_P(PeerConnectionEndToEndTest, CloseDataChannelRemotelyWhileNotReferenced) {
|
||||
// close message and be destroyed.
|
||||
rtc::Thread::Current()->ProcessMessages(100);
|
||||
}
|
||||
|
||||
// Test behavior of creating too many datachannels.
|
||||
TEST_P(PeerConnectionEndToEndTest, TooManyDataChannelsOpenedBeforeConnecting) {
|
||||
CreatePcs(webrtc::MockAudioEncoderFactory::CreateEmptyFactory(),
|
||||
webrtc::MockAudioDecoderFactory::CreateEmptyFactory());
|
||||
|
||||
webrtc::DataChannelInit init;
|
||||
std::vector<rtc::scoped_refptr<DataChannelInterface>> channels;
|
||||
for (int i = 0; i <= cricket::kMaxSctpStreams / 2; i++) {
|
||||
rtc::scoped_refptr<DataChannelInterface> caller_dc(
|
||||
caller_->CreateDataChannel("data", init));
|
||||
channels.push_back(std::move(caller_dc));
|
||||
}
|
||||
Negotiate();
|
||||
WaitForConnection();
|
||||
EXPECT_EQ_WAIT(callee_signaled_data_channels_.size(),
|
||||
static_cast<size_t>(cricket::kMaxSctpStreams / 2), kMaxWait);
|
||||
EXPECT_EQ(DataChannelInterface::kOpen,
|
||||
channels[(cricket::kMaxSctpStreams / 2) - 1]->state());
|
||||
EXPECT_EQ(DataChannelInterface::kClosed,
|
||||
channels[cricket::kMaxSctpStreams / 2]->state());
|
||||
}
|
||||
|
||||
#endif // HAVE_SCTP
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(PeerConnectionEndToEndTest,
|
||||
|
||||
Reference in New Issue
Block a user