Use WeakPtr in SctpDataChannel.
DataChannelController used WeakPtr to clear outstanding references upon destruction - except for the case of SctpDataChannel where we had a pointer+flag for the same purpose. This change updates SctpDataChannel and FakeDataChannelController to use a consistent approach. Bug: none Change-Id: I0248471c241365a2c0de76afbb37302115650194 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/295820 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39464}
This commit is contained in:
parent
24c78f0983
commit
1c0d91f047
@ -883,6 +883,7 @@ rtc_library("sctp_data_channel") {
|
||||
"../rtc_base:ssl",
|
||||
"../rtc_base:threading",
|
||||
"../rtc_base:threading",
|
||||
"../rtc_base:weak_ptr",
|
||||
"../rtc_base/system:unused",
|
||||
"../rtc_base/third_party/sigslot:sigslot",
|
||||
]
|
||||
@ -2783,6 +2784,7 @@ if (rtc_include_tests && !build_with_chromium) {
|
||||
"../rtc_base:task_queue_for_test",
|
||||
"../rtc_base:threading",
|
||||
"../rtc_base:timeutils",
|
||||
"../rtc_base:weak_ptr",
|
||||
"../rtc_base/synchronization:mutex",
|
||||
"../rtc_base/task_utils:repeating_task",
|
||||
"../rtc_base/third_party/sigslot",
|
||||
|
||||
@ -20,14 +20,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
DataChannelController::~DataChannelController() {
|
||||
// Since channels may have multiple owners, we cannot guarantee that
|
||||
// they will be deallocated before destroying the controller.
|
||||
// Therefore, detach them from the controller.
|
||||
for (auto channel : sctp_data_channels_) {
|
||||
channel->DetachFromController();
|
||||
}
|
||||
}
|
||||
DataChannelController::~DataChannelController() {}
|
||||
|
||||
bool DataChannelController::HasDataChannels() const {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
@ -301,8 +294,9 @@ DataChannelController::InternalCreateSctpDataChannel(
|
||||
"because the id is already in use or out of range.";
|
||||
return nullptr;
|
||||
}
|
||||
rtc::scoped_refptr<SctpDataChannel> channel(SctpDataChannel::Create(
|
||||
this, label, new_config, signaling_thread(), network_thread()));
|
||||
rtc::scoped_refptr<SctpDataChannel> channel(
|
||||
SctpDataChannel::Create(weak_factory_.GetWeakPtr(), label, new_config,
|
||||
signaling_thread(), network_thread()));
|
||||
if (!channel) {
|
||||
sid_allocator_.ReleaseSid(new_config.id);
|
||||
return nullptr;
|
||||
|
||||
@ -79,7 +79,7 @@ class SctpDataChannelTest : public ::testing::Test {
|
||||
protected:
|
||||
SctpDataChannelTest()
|
||||
: controller_(new FakeDataChannelController()),
|
||||
webrtc_data_channel_(SctpDataChannel::Create(controller_.get(),
|
||||
webrtc_data_channel_(SctpDataChannel::Create(controller_->weak_ptr(),
|
||||
"test",
|
||||
init_,
|
||||
rtc::Thread::Current(),
|
||||
@ -110,7 +110,7 @@ class SctpDataChannelTest : public ::testing::Test {
|
||||
TEST_F(SctpDataChannelTest, ConnectedToTransportOnCreated) {
|
||||
controller_->set_transport_available(true);
|
||||
rtc::scoped_refptr<SctpDataChannel> dc =
|
||||
SctpDataChannel::Create(controller_.get(), "test1", init_,
|
||||
SctpDataChannel::Create(controller_->weak_ptr(), "test1", init_,
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
|
||||
EXPECT_TRUE(controller_->IsConnected(dc.get()));
|
||||
@ -301,7 +301,7 @@ TEST_F(SctpDataChannelTest, LateCreatedChannelTransitionToOpen) {
|
||||
webrtc::InternalDataChannelInit init;
|
||||
init.id = 1;
|
||||
rtc::scoped_refptr<SctpDataChannel> dc =
|
||||
SctpDataChannel::Create(controller_.get(), "test1", init,
|
||||
SctpDataChannel::Create(controller_->weak_ptr(), "test1", init,
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, dc->state());
|
||||
EXPECT_TRUE_WAIT(webrtc::DataChannelInterface::kOpen == dc->state(), 1000);
|
||||
@ -315,7 +315,7 @@ TEST_F(SctpDataChannelTest, SendUnorderedAfterReceivesOpenAck) {
|
||||
init.id = 1;
|
||||
init.ordered = false;
|
||||
rtc::scoped_refptr<SctpDataChannel> dc =
|
||||
SctpDataChannel::Create(controller_.get(), "test1", init,
|
||||
SctpDataChannel::Create(controller_->weak_ptr(), "test1", init,
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
|
||||
EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
|
||||
@ -346,7 +346,7 @@ TEST_F(SctpDataChannelTest, SendUnorderedAfterReceiveData) {
|
||||
init.id = 1;
|
||||
init.ordered = false;
|
||||
rtc::scoped_refptr<SctpDataChannel> dc =
|
||||
SctpDataChannel::Create(controller_.get(), "test1", init,
|
||||
SctpDataChannel::Create(controller_->weak_ptr(), "test1", init,
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
|
||||
EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
|
||||
@ -450,7 +450,7 @@ TEST_F(SctpDataChannelTest, NoMsgSentIfNegotiatedAndNotFromOpenMsg) {
|
||||
|
||||
SetChannelReady();
|
||||
rtc::scoped_refptr<SctpDataChannel> dc =
|
||||
SctpDataChannel::Create(controller_.get(), "test1", config,
|
||||
SctpDataChannel::Create(controller_->weak_ptr(), "test1", config,
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
|
||||
EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
|
||||
@ -514,7 +514,7 @@ TEST_F(SctpDataChannelTest, OpenAckSentIfCreatedFromOpenMessage) {
|
||||
|
||||
SetChannelReady();
|
||||
rtc::scoped_refptr<SctpDataChannel> dc =
|
||||
SctpDataChannel::Create(controller_.get(), "test1", config,
|
||||
SctpDataChannel::Create(controller_->weak_ptr(), "test1", config,
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
|
||||
EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
|
||||
|
||||
@ -2109,10 +2109,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
|
||||
// TODO(bugs.webrtc.org/11547): Supply a separate network thread.
|
||||
FakeDataChannelController controller;
|
||||
rtc::scoped_refptr<SctpDataChannel> dummy_channel_a = SctpDataChannel::Create(
|
||||
&controller, "DummyChannelA", InternalDataChannelInit(),
|
||||
controller.weak_ptr(), "DummyChannelA", InternalDataChannelInit(),
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
rtc::scoped_refptr<SctpDataChannel> dummy_channel_b = SctpDataChannel::Create(
|
||||
&controller, "DummyChannelB", InternalDataChannelInit(),
|
||||
controller.weak_ptr(), "DummyChannelB", InternalDataChannelInit(),
|
||||
rtc::Thread::Current(), rtc::Thread::Current());
|
||||
|
||||
stats_->stats_collector()->OnSctpDataChannelStateChanged(
|
||||
|
||||
@ -138,14 +138,15 @@ bool SctpSidAllocator::IsSidAvailable(int sid) const {
|
||||
return used_sids_.find(sid) == used_sids_.end();
|
||||
}
|
||||
|
||||
// static
|
||||
rtc::scoped_refptr<SctpDataChannel> SctpDataChannel::Create(
|
||||
SctpDataChannelControllerInterface* controller,
|
||||
rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
|
||||
const std::string& label,
|
||||
const InternalDataChannelInit& config,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* network_thread) {
|
||||
auto channel = rtc::make_ref_counted<SctpDataChannel>(
|
||||
config, controller, label, signaling_thread, network_thread);
|
||||
config, std::move(controller), label, signaling_thread, network_thread);
|
||||
if (!channel->Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -160,27 +161,23 @@ rtc::scoped_refptr<DataChannelInterface> SctpDataChannel::CreateProxy(
|
||||
return DataChannelProxy::Create(signaling_thread, std::move(channel));
|
||||
}
|
||||
|
||||
SctpDataChannel::SctpDataChannel(const InternalDataChannelInit& config,
|
||||
SctpDataChannelControllerInterface* controller,
|
||||
const std::string& label,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* network_thread)
|
||||
SctpDataChannel::SctpDataChannel(
|
||||
const InternalDataChannelInit& config,
|
||||
rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
|
||||
const std::string& label,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* network_thread)
|
||||
: signaling_thread_(signaling_thread),
|
||||
network_thread_(network_thread),
|
||||
internal_id_(GenerateUniqueId()),
|
||||
label_(label),
|
||||
config_(config),
|
||||
observer_(nullptr),
|
||||
controller_(controller) {
|
||||
controller_(std::move(controller)) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread_);
|
||||
RTC_UNUSED(network_thread_);
|
||||
}
|
||||
|
||||
void SctpDataChannel::DetachFromController() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread_);
|
||||
controller_detached_ = true;
|
||||
}
|
||||
|
||||
bool SctpDataChannel::Init() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread_);
|
||||
if (config_.id < -1 ||
|
||||
@ -217,7 +214,7 @@ 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_detached_);
|
||||
RTC_DCHECK(controller_);
|
||||
if (controller_->ReadyToSendData()) {
|
||||
AddRef();
|
||||
absl::Cleanup release = [this] { Release(); };
|
||||
@ -333,7 +330,6 @@ void SctpDataChannel::SetSctpSid(int sid) {
|
||||
}
|
||||
|
||||
const_cast<InternalDataChannelInit&>(config_).id = sid;
|
||||
RTC_DCHECK(!controller_detached_);
|
||||
controller_->AddSctpDataStream(sid);
|
||||
}
|
||||
|
||||
@ -367,7 +363,7 @@ void SctpDataChannel::OnClosingProcedureComplete(int sid) {
|
||||
|
||||
void SctpDataChannel::OnTransportChannelCreated() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread_);
|
||||
if (controller_detached_) {
|
||||
if (!controller_) {
|
||||
return;
|
||||
}
|
||||
if (!connected_to_transport_) {
|
||||
@ -542,7 +538,7 @@ void SctpDataChannel::UpdateState() {
|
||||
// OnClosingProcedureComplete will end up called asynchronously
|
||||
// afterwards.
|
||||
if (connected_to_transport_ && !started_closing_procedure_ &&
|
||||
!controller_detached_ && config_.id >= 0) {
|
||||
controller_ && config_.id >= 0) {
|
||||
started_closing_procedure_ = true;
|
||||
controller_->RemoveSctpDataStream(config_.id);
|
||||
}
|
||||
@ -565,13 +561,13 @@ void SctpDataChannel::SetState(DataState state) {
|
||||
observer_->OnStateChange();
|
||||
}
|
||||
|
||||
if (!controller_detached_)
|
||||
if (controller_)
|
||||
controller_->OnChannelStateChanged(this, state_);
|
||||
}
|
||||
|
||||
void SctpDataChannel::DisconnectFromTransport() {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread_);
|
||||
if (!connected_to_transport_ || controller_detached_)
|
||||
if (!connected_to_transport_ || !controller_)
|
||||
return;
|
||||
|
||||
controller_->DisconnectDataChannel(this);
|
||||
@ -614,7 +610,7 @@ bool SctpDataChannel::SendDataMessage(const DataBuffer& buffer,
|
||||
bool queue_if_blocked) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread_);
|
||||
SendDataParams send_params;
|
||||
if (controller_detached_) {
|
||||
if (!controller_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -696,7 +692,7 @@ bool SctpDataChannel::SendControlMessage(const rtc::CopyOnWriteBuffer& buffer) {
|
||||
RTC_DCHECK(writable_);
|
||||
RTC_DCHECK_GE(config_.id, 0);
|
||||
|
||||
if (controller_detached_) {
|
||||
if (!controller_) {
|
||||
return false;
|
||||
}
|
||||
bool is_open_message = handshake_state_ == kHandshakeShouldSendOpen;
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "rtc_base/third_party/sigslot/sigslot.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
#include "rtc_base/weak_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -123,7 +124,7 @@ class SctpDataChannel : public DataChannelInterface,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
static rtc::scoped_refptr<SctpDataChannel> Create(
|
||||
SctpDataChannelControllerInterface* controller,
|
||||
rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
|
||||
const std::string& label,
|
||||
const InternalDataChannelInit& config,
|
||||
rtc::Thread* signaling_thread,
|
||||
@ -134,9 +135,6 @@ class SctpDataChannel : public DataChannelInterface,
|
||||
static rtc::scoped_refptr<DataChannelInterface> CreateProxy(
|
||||
rtc::scoped_refptr<SctpDataChannel> channel);
|
||||
|
||||
// Invalidate the link to the controller (DataChannelController);
|
||||
void DetachFromController();
|
||||
|
||||
void RegisterObserver(DataChannelObserver* observer) override;
|
||||
void UnregisterObserver() override;
|
||||
|
||||
@ -223,7 +221,7 @@ class SctpDataChannel : public DataChannelInterface,
|
||||
|
||||
protected:
|
||||
SctpDataChannel(const InternalDataChannelInit& config,
|
||||
SctpDataChannelControllerInterface* client,
|
||||
rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
|
||||
const std::string& label,
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* network_thread);
|
||||
@ -266,9 +264,8 @@ class SctpDataChannel : public DataChannelInterface,
|
||||
uint64_t bytes_sent_ RTC_GUARDED_BY(signaling_thread_) = 0;
|
||||
uint32_t messages_received_ RTC_GUARDED_BY(signaling_thread_) = 0;
|
||||
uint64_t bytes_received_ RTC_GUARDED_BY(signaling_thread_) = 0;
|
||||
SctpDataChannelControllerInterface* const controller_
|
||||
rtc::WeakPtr<SctpDataChannelControllerInterface> controller_
|
||||
RTC_GUARDED_BY(signaling_thread_);
|
||||
bool controller_detached_ RTC_GUARDED_BY(signaling_thread_) = false;
|
||||
HandshakeState handshake_state_ RTC_GUARDED_BY(signaling_thread_) =
|
||||
kHandshakeInit;
|
||||
bool connected_to_transport_ RTC_GUARDED_BY(signaling_thread_) = false;
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
#include "pc/sctp_data_channel.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/weak_ptr.h"
|
||||
|
||||
class FakeDataChannelController
|
||||
: public webrtc::SctpDataChannelControllerInterface {
|
||||
@ -26,6 +27,10 @@ class FakeDataChannelController
|
||||
transport_error_(false) {}
|
||||
virtual ~FakeDataChannelController() {}
|
||||
|
||||
rtc::WeakPtr<FakeDataChannelController> weak_ptr() {
|
||||
return weak_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
bool SendData(int sid,
|
||||
const webrtc::SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& payload,
|
||||
@ -171,5 +176,6 @@ class FakeDataChannelController
|
||||
std::set<webrtc::SctpDataChannel*> connected_channels_;
|
||||
std::set<uint32_t> send_ssrcs_;
|
||||
std::set<uint32_t> recv_ssrcs_;
|
||||
rtc::WeakPtrFactory<FakeDataChannelController> weak_factory_{this};
|
||||
};
|
||||
#endif // PC_TEST_FAKE_DATA_CHANNEL_CONTROLLER_H_
|
||||
|
||||
@ -303,9 +303,9 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase {
|
||||
void AddSctpDataChannel(const std::string& label,
|
||||
const InternalDataChannelInit& init) {
|
||||
// TODO(bugs.webrtc.org/11547): Supply a separate network thread.
|
||||
AddSctpDataChannel(SctpDataChannel::Create(&data_channel_controller_, label,
|
||||
init, rtc::Thread::Current(),
|
||||
rtc::Thread::Current()));
|
||||
AddSctpDataChannel(SctpDataChannel::Create(
|
||||
data_channel_controller_.weak_ptr(), label, init,
|
||||
rtc::Thread::Current(), rtc::Thread::Current()));
|
||||
}
|
||||
|
||||
void AddSctpDataChannel(rtc::scoped_refptr<SctpDataChannel> data_channel) {
|
||||
|
||||
@ -42,7 +42,7 @@ class MockSctpDataChannel : public SctpDataChannel {
|
||||
rtc::Thread* signaling_thread = rtc::Thread::Current(),
|
||||
rtc::Thread* network_thread = rtc::Thread::Current())
|
||||
: SctpDataChannel(config,
|
||||
nullptr,
|
||||
rtc::WeakPtr<SctpDataChannelControllerInterface>(),
|
||||
label,
|
||||
signaling_thread,
|
||||
network_thread) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user