/* * 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 namespace webrtc { SctpTransport::SctpTransport( std::unique_ptr 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 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 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