Revert "Fix unsynchronized access to mid_to_transport_ in JsepTransportController"

This reverts commit 6cd405850467683cf10d05028ea0f644a68a91a4.

Reason for revert: Breaks WebRTC Chromium FYI Bots

First failure:
https://ci.chromium.org/p/chromium/builders/webrtc.fyi/WebRTC%20Chromium%20FYI%20Android%20Tests%20%28dbg%29%20%28L%20Nexus5%29/1925

Failed tests:
WebRtcDataBrowserTest.CallWithSctpDataAndMedia
WebRtcDataBrowserTest.CallWithSctpDataOnly

Original change's description:
> Fix unsynchronized access to mid_to_transport_ in JsepTransportController
>
> * Added several thread checks to JTC to help with programmer errors.
> * Avoid a few Invokes() to the network thread here and there such
>   as for fetching sctp transport name for getStats(). The transport
>   name is now cached when it changes on the network thread.
> * JsepTransportController instances now get deleted on the network
>   thread rather than on the signaling thread + issuing an Invoke()
>   in the dtor.
> * Moved some thread hops from JTC over to PC which is where the problem
>   exists and also (imho) makes it easier to see where hops happen in
>   the PC code.
> * The sctp transport is now started asynchronously when we push down the
>   media description.
> * PeerConnection proxy calls GetSctpTransport directly on the network
>   thread instead of to the signaling thread + blocking on the network
>   thread.
> * The above changes simplified things for webrtc::SctpTransport which
>   allowed for removing locking from that class and delete some code.
>
> Bug: webrtc:9987, webrtc:12445
> Change-Id: Ic89a9426e314e1b93c81751d4f732f05fa448fbc
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/205620
> Commit-Queue: Tommi <tommi@webrtc.org>
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#33191}

TBR=tommi@webrtc.org,hta@webrtc.org

Change-Id: I7b2913d5133807589461105cf07eff3e9bb7157e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:9987
Bug: webrtc:12445
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/206466
Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
Commit-Queue: Guido Urdaneta <guidou@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33204}
This commit is contained in:
Guido Urdaneta 2021-02-09 12:21:02 +00:00 committed by Commit Bot
parent 6e4fcac313
commit 6b143c1c06
11 changed files with 141 additions and 237 deletions

View File

@ -20,12 +20,9 @@
namespace webrtc {
// PeerConnection proxy objects will be constructed with two thread pointers,
// signaling and network. The proxy macros don't have 'network' specific macros
// and support for a secondary thread is provided via 'WORKER' macros.
// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
// are called on is an implementation detail.
BEGIN_PROXY_MAP(PeerConnection)
BEGIN_SIGNALING_PROXY_MAP(PeerConnection)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_METHOD0(rtc::scoped_refptr<StreamCollectionInterface>, local_streams)
PROXY_METHOD0(rtc::scoped_refptr<StreamCollectionInterface>, remote_streams)
@ -136,10 +133,7 @@ PROXY_METHOD1(void, SetAudioRecording, bool)
PROXY_METHOD1(rtc::scoped_refptr<DtlsTransportInterface>,
LookupDtlsTransportByMid,
const std::string&)
// This method will be invoked on the network thread. See
// PeerConnectionFactory::CreatePeerConnectionOrError for more details.
PROXY_WORKER_CONSTMETHOD0(rtc::scoped_refptr<SctpTransportInterface>,
GetSctpTransport)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<SctpTransportInterface>, GetSctpTransport)
PROXY_METHOD0(SignalingState, signaling_state)
PROXY_METHOD0(IceConnectionState, ice_connection_state)
PROXY_METHOD0(IceConnectionState, standardized_ice_connection_state)

View File

@ -105,8 +105,10 @@ JsepTransportController::JsepTransportController(
JsepTransportController::~JsepTransportController() {
// Channel destructors may try to send packets, so this needs to happen on
// the network thread.
network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
RTC_DCHECK_RUN_ON(network_thread_);
DestroyAllJsepTransports_n();
});
}
RTCError JsepTransportController::SetLocalDescription(
@ -143,7 +145,6 @@ RTCError JsepTransportController::SetRemoteDescription(
RtpTransportInternal* JsepTransportController::GetRtpTransport(
const std::string& mid) const {
RTC_DCHECK_RUN_ON(network_thread_);
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -153,7 +154,6 @@ RtpTransportInternal* JsepTransportController::GetRtpTransport(
DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
const std::string& mid) const {
RTC_DCHECK_RUN_ON(network_thread_);
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -163,7 +163,6 @@ DataChannelTransportInterface* JsepTransportController::GetDataChannelTransport(
cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
const std::string& mid) {
RTC_DCHECK_RUN_ON(network_thread_);
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -173,7 +172,6 @@ cricket::DtlsTransportInternal* JsepTransportController::GetDtlsTransport(
const cricket::DtlsTransportInternal*
JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
RTC_DCHECK_RUN_ON(network_thread_);
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -183,7 +181,6 @@ JsepTransportController::GetRtcpDtlsTransport(const std::string& mid) const {
rtc::scoped_refptr<webrtc::DtlsTransport>
JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
RTC_DCHECK_RUN_ON(network_thread_);
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -193,7 +190,6 @@ JsepTransportController::LookupDtlsTransportByMid(const std::string& mid) {
rtc::scoped_refptr<SctpTransport> JsepTransportController::GetSctpTransport(
const std::string& mid) const {
RTC_DCHECK_RUN_ON(network_thread_);
auto jsep_transport = GetJsepTransportForMid(mid);
if (!jsep_transport) {
return nullptr;
@ -240,16 +236,11 @@ bool JsepTransportController::NeedsIceRestart(
absl::optional<rtc::SSLRole> JsepTransportController::GetDtlsRole(
const std::string& mid) const {
// TODO(tommi): Remove this hop. Currently it's called from the signaling
// thread during negotiations, potentially multiple times.
// WebRtcSessionDescriptionFactory::InternalCreateAnswer is one example.
if (!network_thread_->IsCurrent()) {
return network_thread_->Invoke<absl::optional<rtc::SSLRole>>(
RTC_FROM_HERE, [&] { return GetDtlsRole(mid); });
}
RTC_DCHECK_RUN_ON(network_thread_);
const cricket::JsepTransport* t = GetJsepTransportForMid(mid);
if (!t) {
return absl::optional<rtc::SSLRole>();
@ -855,34 +846,24 @@ bool JsepTransportController::HandleBundledContent(
bool JsepTransportController::SetTransportForMid(
const std::string& mid,
cricket::JsepTransport* jsep_transport) {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_DCHECK(jsep_transport);
auto it = mid_to_transport_.find(mid);
if (it != mid_to_transport_.end() && it->second == jsep_transport)
if (mid_to_transport_[mid] == jsep_transport) {
return true;
pending_mids_.push_back(mid);
if (it == mid_to_transport_.end()) {
mid_to_transport_.insert(std::make_pair(mid, jsep_transport));
} else {
it->second = jsep_transport;
}
RTC_DCHECK_RUN_ON(network_thread_);
pending_mids_.push_back(mid);
mid_to_transport_[mid] = jsep_transport;
return config_.transport_observer->OnTransportChanged(
mid, jsep_transport->rtp_transport(), jsep_transport->RtpDtlsTransport(),
jsep_transport->data_channel_transport());
}
void JsepTransportController::RemoveTransportForMid(const std::string& mid) {
RTC_DCHECK_RUN_ON(network_thread_);
bool ret = config_.transport_observer->OnTransportChanged(mid, nullptr,
nullptr, nullptr);
// Calling OnTransportChanged with nullptr should always succeed, since it is
// only expected to fail when adding media to a transport (not removing).
RTC_DCHECK(ret);
mid_to_transport_.erase(mid);
}

View File

@ -363,9 +363,8 @@ class JsepTransportController : public sigslot::has_slots<> {
// transports are bundled on (In current implementation, it is the first
// content in the BUNDLE group).
const cricket::JsepTransport* GetJsepTransportForMid(
const std::string& mid) const RTC_RUN_ON(network_thread_);
cricket::JsepTransport* GetJsepTransportForMid(const std::string& mid)
RTC_RUN_ON(network_thread_);
const std::string& mid) const;
cricket::JsepTransport* GetJsepTransportForMid(const std::string& mid);
// Get the JsepTransport without considering the BUNDLE group. Return nullptr
// if the JsepTransport is destroyed.
@ -461,8 +460,7 @@ class JsepTransportController : public sigslot::has_slots<> {
jsep_transports_by_name_ RTC_GUARDED_BY(network_thread_);
// This keeps track of the mapping between media section
// (BaseChannel/SctpTransport) and the JsepTransport underneath.
std::map<std::string, cricket::JsepTransport*> mid_to_transport_
RTC_GUARDED_BY(network_thread_);
std::map<std::string, cricket::JsepTransport*> mid_to_transport_;
// Keep track of mids that have been mapped to transports. Used for rollback.
std::vector<std::string> pending_mids_ RTC_GUARDED_BY(network_thread_);
// Aggregate states for Transports.

View File

@ -904,9 +904,6 @@ TEST_F(JsepTransportControllerTest, IceSignalingOccursOnSignalingThread) {
EXPECT_EQ(2, candidates_signal_count_);
EXPECT_TRUE(!signaled_on_non_signaling_thread_);
network_thread_->Invoke<void>(RTC_FROM_HERE,
[&] { transport_controller_.reset(); });
}
// Test that if the TransportController was created with the

View File

@ -489,17 +489,12 @@ PeerConnection::~PeerConnection() {
sdp_handler_->ResetSessionDescFactory();
}
transport_controller_.reset();
// port_allocator_ and transport_controller_ live on the network thread and
// should be destroyed there.
// port_allocator_ lives on the network thread and should be destroyed there.
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
RTC_DCHECK_RUN_ON(network_thread());
transport_controller_.reset();
port_allocator_.reset();
if (network_thread_safety_) {
network_thread_safety_->SetNotAlive();
network_thread_safety_ = nullptr;
}
});
// call_ and event_log_ must be destroyed on the worker thread.
worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
@ -532,15 +527,13 @@ RTCError PeerConnection::Initialize(
}
// The port allocator lives on the network thread and should be initialized
// there. Also set up the task safety flag for canceling pending tasks on
// the network thread when closing.
// there.
// TODO(bugs.webrtc.org/12427): See if we can piggyback on this call and
// initialize all the |transport_controller_->Subscribe*| calls below on the
// network thread via this invoke.
const auto pa_result =
network_thread()->Invoke<InitializePortAllocatorResult>(
RTC_FROM_HERE, [this, &stun_servers, &turn_servers, &configuration] {
network_thread_safety_ = PendingTaskSafetyFlag::Create();
return InitializePortAllocator_n(stun_servers, turn_servers,
configuration);
});
@ -839,16 +832,6 @@ PeerConnection::AddTransceiver(
return AddTransceiver(track, RtpTransceiverInit());
}
RtpTransportInternal* PeerConnection::GetRtpTransport(const std::string& mid) {
RTC_DCHECK_RUN_ON(signaling_thread());
return network_thread()->Invoke<RtpTransportInternal*>(
RTC_FROM_HERE, [this, &mid] {
auto rtp_transport = transport_controller_->GetRtpTransport(mid);
RTC_DCHECK(rtp_transport);
return rtp_transport;
});
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
PeerConnection::AddTransceiver(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
@ -1605,11 +1588,11 @@ PeerConnection::LookupDtlsTransportByMidInternal(const std::string& mid) {
rtc::scoped_refptr<SctpTransportInterface> PeerConnection::GetSctpTransport()
const {
RTC_DCHECK_RUN_ON(network_thread());
if (!sctp_mid_n_)
RTC_DCHECK_RUN_ON(signaling_thread());
if (!sctp_mid_s_) {
return nullptr;
return transport_controller_->GetSctpTransport(*sctp_mid_n_);
}
return transport_controller_->GetSctpTransport(*sctp_mid_s_);
}
const SessionDescriptionInterface* PeerConnection::local_description() const {
@ -1690,16 +1673,11 @@ void PeerConnection::Close() {
// WebRTC session description factory, the session description factory would
// call the transport controller.
sdp_handler_->ResetSessionDescFactory();
transport_controller_.reset();
rtp_manager_->Close();
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
transport_controller_.reset();
port_allocator_->DiscardCandidatePool();
if (network_thread_safety_) {
network_thread_safety_->SetNotAlive();
network_thread_safety_ = nullptr;
}
});
network_thread()->Invoke<void>(
RTC_FROM_HERE, [this] { port_allocator_->DiscardCandidatePool(); });
worker_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
RTC_DCHECK_RUN_ON(worker_thread());
@ -1832,17 +1810,6 @@ absl::optional<std::string> PeerConnection::GetDataMid() const {
}
}
void PeerConnection::SetSctpDataMid(const std::string& mid) {
RTC_DCHECK_RUN_ON(signaling_thread());
sctp_mid_s_ = mid;
}
void PeerConnection::ResetSctpDataMid() {
RTC_DCHECK_RUN_ON(signaling_thread());
sctp_mid_s_.reset();
sctp_transport_name_s_.clear();
}
void PeerConnection::OnSctpDataChannelClosed(DataChannelInterface* channel) {
// Since data_channel_controller doesn't do signals, this
// signal is relayed here.
@ -2056,8 +2023,13 @@ std::vector<DataChannelStats> PeerConnection::GetDataChannelStats() const {
absl::optional<std::string> PeerConnection::sctp_transport_name() const {
RTC_DCHECK_RUN_ON(signaling_thread());
if (sctp_mid_s_ && transport_controller_)
return sctp_transport_name_s_;
if (sctp_mid_s_ && transport_controller_) {
auto dtls_transport = transport_controller_->GetDtlsTransport(*sctp_mid_s_);
if (dtls_transport) {
return dtls_transport->transport_name();
}
return absl::optional<std::string>();
}
return absl::optional<std::string>();
}
@ -2296,15 +2268,6 @@ bool PeerConnection::SetupDataChannelTransport_n(const std::string& mid) {
data_channel_controller_.set_data_channel_transport(transport);
data_channel_controller_.SetupDataChannelTransport_n();
sctp_mid_n_ = mid;
auto dtls_transport = transport_controller_->GetDtlsTransport(mid);
if (dtls_transport) {
signaling_thread()->PostTask(
ToQueuedTask(signaling_thread_safety_.flag(),
[this, name = dtls_transport->transport_name()] {
RTC_DCHECK_RUN_ON(signaling_thread());
sctp_transport_name_s_ = std::move(name);
}));
}
// Note: setting the data sink and checking initial state must be done last,
// after setting up the data channel. Setting the data sink may trigger
@ -2649,19 +2612,9 @@ bool PeerConnection::OnTransportChanged(
if (base_channel) {
ret = base_channel->SetRtpTransport(rtp_transport);
}
if (mid == sctp_mid_n_) {
data_channel_controller_.OnTransportChanged(data_channel_transport);
if (dtls_transport) {
signaling_thread()->PostTask(ToQueuedTask(
signaling_thread_safety_.flag(),
[this, name = dtls_transport->internal()->transport_name()] {
RTC_DCHECK_RUN_ON(signaling_thread());
sctp_transport_name_s_ = std::move(name);
}));
}
}
return ret;
}
@ -2671,23 +2624,6 @@ PeerConnectionObserver* PeerConnection::Observer() const {
return observer_;
}
void PeerConnection::StartSctpTransport(int local_port,
int remote_port,
int max_message_size) {
RTC_DCHECK_RUN_ON(signaling_thread());
if (!sctp_mid_s_)
return;
network_thread()->PostTask(ToQueuedTask(
network_thread_safety_,
[this, mid = *sctp_mid_s_, local_port, remote_port, max_message_size] {
rtc::scoped_refptr<SctpTransport> sctp_transport =
transport_controller()->GetSctpTransport(mid);
if (sctp_transport)
sctp_transport->Start(local_port, remote_port, max_message_size);
}));
}
CryptoOptions PeerConnection::GetCryptoOptions() {
RTC_DCHECK_RUN_ON(signaling_thread());
// TODO(bugs.webrtc.org/9891) - Remove PeerConnectionFactory::CryptoOptions

View File

@ -404,15 +404,14 @@ class PeerConnection : public PeerConnectionInternal,
// channels are configured this will return nullopt.
absl::optional<std::string> GetDataMid() const;
void SetSctpDataMid(const std::string& mid);
void ResetSctpDataMid();
// Asynchronously calls SctpTransport::Start() on the network thread for
// |sctp_mid()| if set. Called as part of setting the local description.
void StartSctpTransport(int local_port,
int remote_port,
int max_message_size);
void SetSctpDataMid(const std::string& mid) {
RTC_DCHECK_RUN_ON(signaling_thread());
sctp_mid_s_ = mid;
}
void ResetSctpDataMid() {
RTC_DCHECK_RUN_ON(signaling_thread());
sctp_mid_s_.reset();
}
// Returns the CryptoOptions for this PeerConnection. This will always
// return the RTCConfiguration.crypto_options if set and will only default
@ -428,7 +427,12 @@ class PeerConnection : public PeerConnectionInternal,
bool fire_callback = true);
// Returns rtp transport, result can not be nullptr.
RtpTransportInternal* GetRtpTransport(const std::string& mid);
RtpTransportInternal* GetRtpTransport(const std::string& mid) {
RTC_DCHECK_RUN_ON(signaling_thread());
auto rtp_transport = transport_controller_->GetRtpTransport(mid);
RTC_DCHECK(rtp_transport);
return rtp_transport;
}
// Returns true if SRTP (either using DTLS-SRTP or SDES) is required by
// this session.
@ -644,8 +648,6 @@ class PeerConnection : public PeerConnectionInternal,
// The unique_ptr belongs to the worker thread, but the Call object manages
// its own thread safety.
std::unique_ptr<Call> call_ RTC_GUARDED_BY(worker_thread());
ScopedTaskSafety signaling_thread_safety_;
rtc::scoped_refptr<PendingTaskSafetyFlag> network_thread_safety_;
std::unique_ptr<ScopedTaskSafety> call_safety_
RTC_GUARDED_BY(worker_thread());
@ -675,7 +677,6 @@ class PeerConnection : public PeerConnectionInternal,
// thread, but applied first on the networking thread via an invoke().
absl::optional<std::string> sctp_mid_s_ RTC_GUARDED_BY(signaling_thread());
absl::optional<std::string> sctp_mid_n_ RTC_GUARDED_BY(network_thread());
std::string sctp_transport_name_s_ RTC_GUARDED_BY(signaling_thread());
// The machinery for handling offers and answers. Const after initialization.
std::unique_ptr<SdpOfferAnswerHandler> sdp_handler_

View File

@ -265,15 +265,8 @@ PeerConnectionFactory::CreatePeerConnectionOrError(
if (!result.ok()) {
return result.MoveError();
}
// We configure the proxy with a pointer to the network thread for methods
// that need to be invoked there rather than on the signaling thread.
// Internally, the proxy object has a member variable named |worker_thread_|
// which will point to the network thread (and not the factory's
// worker_thread()). All such methods have thread checks though, so the code
// should still be clear (outside of macro expansion).
rtc::scoped_refptr<PeerConnectionInterface> result_proxy =
PeerConnectionProxy::Create(signaling_thread(), network_thread(),
result.MoveValue());
PeerConnectionProxy::Create(signaling_thread(), result.MoveValue());
return result_proxy;
}

View File

@ -5969,11 +5969,9 @@ TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
callee()->AddAudioVideoTracks();
caller()->CreateAndSetAndSignalOffer();
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
ASSERT_EQ_WAIT(SctpTransportState::kConnected,
caller()->pc()->GetSctpTransport()->Information().state(),
kDefaultTimeout);
});
ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
}

View File

@ -45,7 +45,7 @@ SctpTransport::~SctpTransport() {
}
SctpTransportInformation SctpTransport::Information() const {
RTC_DCHECK_RUN_ON(owner_thread_);
MutexLock lock(&lock_);
return info_;
}
@ -71,17 +71,23 @@ rtc::scoped_refptr<DtlsTransportInterface> SctpTransport::dtls_transport()
void SctpTransport::Clear() {
RTC_DCHECK_RUN_ON(owner_thread_);
RTC_DCHECK(internal());
{
MutexLock lock(&lock_);
// Note that we delete internal_sctp_transport_, but
// only drop the reference to dtls_transport_.
dtls_transport_ = nullptr;
internal_sctp_transport_ = nullptr;
}
UpdateInformation(SctpTransportState::kClosed);
}
void SctpTransport::SetDtlsTransport(
rtc::scoped_refptr<DtlsTransport> transport) {
RTC_DCHECK_RUN_ON(owner_thread_);
SctpTransportState next_state = info_.state();
SctpTransportState next_state;
{
MutexLock lock(&lock_);
next_state = info_.state();
dtls_transport_ = transport;
if (internal_sctp_transport_) {
if (transport) {
@ -95,26 +101,39 @@ void SctpTransport::SetDtlsTransport(
internal_sctp_transport_->SetDtlsTransport(nullptr);
}
}
}
UpdateInformation(next_state);
}
void SctpTransport::Start(int local_port,
int remote_port,
int max_message_size) {
RTC_DCHECK_RUN_ON(owner_thread_);
{
MutexLock lock(&lock_);
// Record max message size on calling thread.
info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
max_message_size, info_.MaxChannels());
}
if (owner_thread_->IsCurrent()) {
if (!internal()->Start(local_port, remote_port, max_message_size)) {
RTC_LOG(LS_ERROR) << "Failed to push down SCTP parameters, closing.";
UpdateInformation(SctpTransportState::kClosed);
}
} else {
owner_thread_->Invoke<void>(
RTC_FROM_HERE, [this, local_port, remote_port, max_message_size] {
Start(local_port, remote_port, max_message_size);
});
}
}
void SctpTransport::UpdateInformation(SctpTransportState state) {
RTC_DCHECK_RUN_ON(owner_thread_);
bool must_send_update = (state != info_.state());
bool must_send_update;
SctpTransportInformation info_copy(SctpTransportState::kNew);
{
MutexLock lock(&lock_);
must_send_update = (state != info_.state());
// TODO(https://bugs.webrtc.org/10358): Update max channels from internal
// SCTP transport when available.
if (internal_sctp_transport_) {
@ -124,14 +143,20 @@ void SctpTransport::UpdateInformation(SctpTransportState state) {
info_ = SctpTransportInformation(
state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
}
if (observer_ && must_send_update) {
observer_->OnStateChange(info_);
info_copy = info_;
}
}
// We call the observer without holding the lock.
if (observer_ && must_send_update) {
observer_->OnStateChange(info_copy);
}
}
void SctpTransport::OnAssociationChangeCommunicationUp() {
RTC_DCHECK_RUN_ON(owner_thread_);
{
MutexLock lock(&lock_);
RTC_DCHECK(internal_sctp_transport_);
if (internal_sctp_transport_->max_outbound_streams() &&
internal_sctp_transport_->max_inbound_streams()) {
@ -142,7 +167,7 @@ void SctpTransport::OnAssociationChangeCommunicationUp() {
info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
info_.MaxMessageSize(), max_channels);
}
}
UpdateInformation(SctpTransportState::kConnected);
}

View File

@ -20,6 +20,7 @@
#include "media/sctp/sctp_transport_internal.h"
#include "p2p/base/dtls_transport_internal.h"
#include "pc/dtls_transport.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h"
@ -53,12 +54,12 @@ class SctpTransport : public SctpTransportInterface,
// internal() to be functions on the webrtc::SctpTransport interface,
// and make the internal() function private.
cricket::SctpTransportInternal* internal() {
RTC_DCHECK_RUN_ON(owner_thread_);
MutexLock lock(&lock_);
return internal_sctp_transport_.get();
}
const cricket::SctpTransportInternal* internal() const {
RTC_DCHECK_RUN_ON(owner_thread_);
MutexLock lock(&lock_);
return internal_sctp_transport_.get();
}
@ -74,12 +75,15 @@ class SctpTransport : public SctpTransportInterface,
void OnDtlsStateChange(cricket::DtlsTransportInternal* transport,
cricket::DtlsTransportState state);
// NOTE: |owner_thread_| is the thread that the SctpTransport object is
// constructed on. In the context of PeerConnection, it's the network thread.
rtc::Thread* const owner_thread_;
SctpTransportInformation info_ RTC_GUARDED_BY(owner_thread_);
// Note - owner_thread never changes, but can't be const if we do
// Invoke() on it.
rtc::Thread* owner_thread_;
mutable Mutex lock_;
// Variables accessible off-thread, guarded by lock_
SctpTransportInformation info_ RTC_GUARDED_BY(lock_);
std::unique_ptr<cricket::SctpTransportInternal> internal_sctp_transport_
RTC_GUARDED_BY(owner_thread_);
RTC_GUARDED_BY(lock_);
// Variables only accessed on-thread
SctpTransportObserverInterface* observer_ RTC_GUARDED_BY(owner_thread_) =
nullptr;
rtc::scoped_refptr<DtlsTransport> dtls_transport_

View File

@ -729,21 +729,6 @@ bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams,
return true;
}
rtc::scoped_refptr<webrtc::DtlsTransport> LookupDtlsTransportByMid(
rtc::Thread* network_thread,
JsepTransportController* controller,
const std::string& mid) {
// TODO(tommi): Can we post this (and associated operations where this
// function is called) to the network thread and avoid this Invoke?
// We might be able to simplify a few things if we set the transport on
// the network thread and then update the implementation to check that
// the set_ and relevant get methods are always called on the network
// thread (we'll need to update proxy maps).
return network_thread->Invoke<rtc::scoped_refptr<webrtc::DtlsTransport>>(
RTC_FROM_HERE,
[controller, &mid] { return controller->LookupDtlsTransportByMid(mid); });
}
} // namespace
// Used by parameterless SetLocalDescription() to create an offer or answer.
@ -1323,8 +1308,8 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
// Note that code paths that don't set MID won't be able to use
// information about DTLS transports.
if (transceiver->mid()) {
auto dtls_transport = LookupDtlsTransportByMid(
pc_->network_thread(), transport_controller(), *transceiver->mid());
auto dtls_transport = transport_controller()->LookupDtlsTransportByMid(
*transceiver->mid());
transceiver->internal()->sender_internal()->set_transport(
dtls_transport);
transceiver->internal()->receiver_internal()->set_transport(
@ -1740,8 +1725,8 @@ RTCError SdpOfferAnswerHandler::ApplyRemoteDescription(
transceiver->internal()->set_current_direction(local_direction);
// 2.2.8.1.11.[3-6]: Set the transport internal slots.
if (transceiver->mid()) {
auto dtls_transport = LookupDtlsTransportByMid(pc_->network_thread(),
transport_controller(),
auto dtls_transport =
transport_controller()->LookupDtlsTransportByMid(
*transceiver->mid());
transceiver->internal()->sender_internal()->set_transport(
dtls_transport);
@ -4291,11 +4276,13 @@ RTCError SdpOfferAnswerHandler::PushdownMediaDescription(
// Need complete offer/answer with an SCTP m= section before starting SCTP,
// according to https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-19
if (pc_->sctp_mid() && local_description() && remote_description()) {
rtc::scoped_refptr<SctpTransport> sctp_transport =
transport_controller()->GetSctpTransport(*(pc_->sctp_mid()));
auto local_sctp_description = cricket::GetFirstSctpDataContentDescription(
local_description()->description());
auto remote_sctp_description = cricket::GetFirstSctpDataContentDescription(
remote_description()->description());
if (local_sctp_description && remote_sctp_description) {
if (sctp_transport && local_sctp_description && remote_sctp_description) {
int max_message_size;
// A remote max message size of zero means "any size supported".
// We configure the connection with our own max message size.
@ -4306,9 +4293,8 @@ RTCError SdpOfferAnswerHandler::PushdownMediaDescription(
std::min(local_sctp_description->max_message_size(),
remote_sctp_description->max_message_size());
}
pc_->StartSctpTransport(local_sctp_description->port(),
remote_sctp_description->port(),
max_message_size);
sctp_transport->Start(local_sctp_description->port(),
remote_sctp_description->port(), max_message_size);
}
}
@ -4534,16 +4520,8 @@ bool SdpOfferAnswerHandler::ReadyToUseRemoteCandidate(
return false;
}
bool has_transport = false;
cricket::ChannelInterface* channel = pc_->GetChannel(result.value()->name);
if (channel) {
has_transport = !channel->transport_name().empty();
} else if (data_channel_controller()->data_channel_transport()) {
auto sctp_mid = pc_->sctp_mid();
RTC_DCHECK(sctp_mid);
has_transport = (result.value()->name == *sctp_mid);
}
return has_transport;
std::string transport_name = GetTransportName(result.value()->name);
return !transport_name.empty();
}
void SdpOfferAnswerHandler::ReportRemoteIceCandidateAdded(
@ -4666,7 +4644,6 @@ cricket::VoiceChannel* SdpOfferAnswerHandler::CreateVoiceChannel(
cricket::VideoChannel* SdpOfferAnswerHandler::CreateVideoChannel(
const std::string& mid) {
RTC_DCHECK_RUN_ON(signaling_thread());
// NOTE: This involves a non-ideal hop (Invoke) over to the network thread.
RtpTransportInternal* rtp_transport = pc_->GetRtpTransport(mid);
// TODO(bugs.webrtc.org/11992): CreateVideoChannel internally switches to the