Simplify SctpDataChannel construction a bit.

This moves SctpDataChannel construction a step closer to RAII by moving the error checks out of SctpDataChannel::Init() and not construct an SctpDataChannel instance unless error checks have been done first in SctpDataChannel::Create.

Ideally the Init() method shouldn't be needed but there is test code that constructs an SctpDataChannel instance without running the Init()
steps but they're required by the SctpDataChannel::Create() path.

Bug: none
Change-Id: I8498693063c28355f901d27c4fe7bd45b7d4be26
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/295860
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39467}
This commit is contained in:
Tommi 2023-03-03 11:28:23 +01:00 committed by WebRTC LUCI CQ
parent 65a6ecab33
commit c2429a080d
2 changed files with 37 additions and 23 deletions

View File

@ -101,6 +101,23 @@ InternalDataChannelInit::InternalDataChannelInit(const DataChannelInit& base)
}
}
bool InternalDataChannelInit::IsValid() const {
if (id < -1)
return false;
if (maxRetransmits.has_value() && maxRetransmits.value() < 0)
return false;
if (maxRetransmitTime.has_value() && maxRetransmitTime.value() < 0)
return false;
// Only one of these can be set.
if (maxRetransmits.has_value() && maxRetransmitTime.has_value())
return false;
return true;
}
bool SctpSidAllocator::AllocateSid(rtc::SSLRole role, int* sid) {
int potential_sid = (role == rtc::SSL_CLIENT) ? 0 : 1;
while (!IsSidAvailable(potential_sid)) {
@ -145,11 +162,17 @@ rtc::scoped_refptr<SctpDataChannel> SctpDataChannel::Create(
const InternalDataChannelInit& config,
rtc::Thread* signaling_thread,
rtc::Thread* network_thread) {
auto channel = rtc::make_ref_counted<SctpDataChannel>(
config, std::move(controller), label, signaling_thread, network_thread);
if (!channel->Init()) {
RTC_DCHECK(controller);
if (!config.IsValid()) {
RTC_LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
"invalid DataChannelInit.";
return nullptr;
}
auto channel = rtc::make_ref_counted<SctpDataChannel>(
config, std::move(controller), label, signaling_thread, network_thread);
channel->Init();
return channel;
}
@ -176,22 +199,7 @@ SctpDataChannel::SctpDataChannel(
controller_(std::move(controller)) {
RTC_DCHECK_RUN_ON(signaling_thread_);
RTC_UNUSED(network_thread_);
}
bool SctpDataChannel::Init() {
RTC_DCHECK_RUN_ON(signaling_thread_);
if (config_.id < -1 ||
(config_.maxRetransmits && *config_.maxRetransmits < 0) ||
(config_.maxRetransmitTime && *config_.maxRetransmitTime < 0)) {
RTC_LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
"invalid DataChannelInit.";
return false;
}
if (config_.maxRetransmits && config_.maxRetransmitTime) {
RTC_LOG(LS_ERROR)
<< "maxRetransmits and maxRetransmitTime should not be both set.";
return false;
}
RTC_DCHECK(config_.IsValid());
switch (config_.open_handshake_role) {
case webrtc::InternalDataChannelInit::kNone: // pre-negotiated
@ -204,6 +212,10 @@ bool SctpDataChannel::Init() {
handshake_state_ = kHandshakeShouldSendAck;
break;
}
}
void SctpDataChannel::Init() {
RTC_DCHECK_RUN_ON(signaling_thread_);
// Try to connect to the transport in case the transport channel already
// exists.
@ -214,7 +226,6 @@ bool SctpDataChannel::Init() {
// This has to be done async because the upper layer objects (e.g.
// Chrome glue and WebKit) are not wired up properly until after this
// function returns.
RTC_DCHECK(controller_);
if (controller_->ReadyToSendData()) {
AddRef();
absl::Cleanup release = [this] { Release(); };
@ -224,8 +235,6 @@ bool SctpDataChannel::Init() {
OnTransportReady(true);
});
}
return true;
}
SctpDataChannel::~SctpDataChannel() {

View File

@ -71,6 +71,11 @@ struct InternalDataChannelInit : public DataChannelInit {
// The default role is kOpener because the default `negotiated` is false.
InternalDataChannelInit() : open_handshake_role(kOpener) {}
explicit InternalDataChannelInit(const DataChannelInit& base);
// Does basic validation to determine if a data channel instance can be
// constructed using the configuration.
bool IsValid() const;
OpenHandshakeRole open_handshake_role;
};
@ -237,7 +242,7 @@ class SctpDataChannel : public DataChannelInterface,
kHandshakeReady
};
bool Init();
void Init();
void UpdateState();
void SetState(DataState state);
void DisconnectFromTransport();