blob: 99270e2eec1843d9f2cad141127f7df8c9661f02 [file] [log] [blame]
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "pc/sctp_transport.h"
#include <utility>
namespace webrtc {
SctpTransport::SctpTransport(
std::unique_ptr<cricket::SctpTransportInternal> internal)
: owner_thread_(rtc::Thread::Current()),
info_(SctpTransportState::kNew),
internal_sctp_transport_(std::move(internal)) {
RTC_DCHECK(internal_sctp_transport_.get());
internal_sctp_transport_->SignalReadyToSendData.connect(
this, &SctpTransport::OnInternalReadyToSendData);
// TODO(https://bugs.webrtc.org/10360): Add handlers for transport closing.
if (dtls_transport_) {
UpdateInformation(SctpTransportState::kConnecting);
} else {
UpdateInformation(SctpTransportState::kNew);
}
}
SctpTransport::~SctpTransport() {
// We depend on the network thread to call Clear() before dropping
// its last reference to this object.
RTC_DCHECK(owner_thread_->IsCurrent() || !internal_sctp_transport_);
}
SctpTransportInformation SctpTransport::Information() const {
rtc::CritScope scope(&lock_);
return info_;
}
void SctpTransport::RegisterObserver(SctpTransportObserverInterface* observer) {
RTC_DCHECK_RUN_ON(owner_thread_);
RTC_DCHECK(observer);
RTC_DCHECK(!observer_);
observer_ = observer;
}
void SctpTransport::UnregisterObserver() {
RTC_DCHECK_RUN_ON(owner_thread_);
observer_ = nullptr;
}
rtc::scoped_refptr<DtlsTransportInterface> SctpTransport::dtls_transport()
const {
RTC_DCHECK_RUN_ON(owner_thread_);
return dtls_transport_;
}
// Internal functions
void SctpTransport::Clear() {
RTC_DCHECK_RUN_ON(owner_thread_);
RTC_DCHECK(internal());
{
rtc::CritScope scope(&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_);
rtc::CritScope scope(&lock_);
dtls_transport_ = transport;
if (internal_sctp_transport_) {
if (transport) {
internal_sctp_transport_->SetDtlsTransport(transport->internal());
if (info_.state() == SctpTransportState::kNew) {
UpdateInformation(SctpTransportState::kConnecting);
}
} else {
internal_sctp_transport_->SetDtlsTransport(nullptr);
}
}
}
void SctpTransport::UpdateInformation(SctpTransportState state) {
RTC_DCHECK_RUN_ON(owner_thread_);
bool must_send_update;
SctpTransportInformation info_copy(SctpTransportState::kNew);
{
rtc::CritScope scope(&lock_);
must_send_update = (state != info_.state());
// TODO(https://bugs.webrtc.org/10358): Update max message size and
// max channels from internal SCTP transport when available.
info_ = SctpTransportInformation(
state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
if (observer_ && must_send_update) {
info_copy = info_;
}
}
// We call the observer without holding the lock.
if (observer_ && must_send_update) {
observer_->OnStateChange(info_copy);
}
}
void SctpTransport::OnInternalReadyToSendData() {
UpdateInformation(SctpTransportState::kConnected);
}
} // namespace webrtc