diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/pc/sctp_transport.cc | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/pc/sctp_transport.cc')
-rw-r--r-- | third_party/libwebrtc/pc/sctp_transport.cc | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/sctp_transport.cc b/third_party/libwebrtc/pc/sctp_transport.cc new file mode 100644 index 0000000000..eabaa04a57 --- /dev/null +++ b/third_party/libwebrtc/pc/sctp_transport.cc @@ -0,0 +1,218 @@ +/* + * 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 <algorithm> +#include <utility> + +#include "absl/types/optional.h" +#include "api/dtls_transport_interface.h" +#include "api/sequence_checker.h" +#include "rtc_base/checks.h" +#include "rtc_base/logging.h" + +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_->SetOnConnectedCallback( + [this]() { OnAssociationChangeCommunicationUp(); }); + + 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 { + // TODO(tommi): Update PeerConnection::GetSctpTransport to hand out a proxy + // to the transport so that we can be sure that methods get called on the + // expected thread. Chromium currently calls this method from + // TransceiverStateSurfacer. + if (!owner_thread_->IsCurrent()) { + return owner_thread_->BlockingCall([this] { return Information(); }); + } + RTC_DCHECK_RUN_ON(owner_thread_); + 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; +} + +RTCError SctpTransport::OpenChannel(int channel_id) { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_DCHECK(internal_sctp_transport_); + internal_sctp_transport_->OpenStream(channel_id); + return RTCError::OK(); +} + +RTCError SctpTransport::SendData(int channel_id, + const SendDataParams& params, + const rtc::CopyOnWriteBuffer& buffer) { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_DCHECK(internal_sctp_transport_); + cricket::SendDataResult result; + internal_sctp_transport_->SendData(channel_id, params, buffer, &result); + + // TODO(mellem): See about changing the interfaces to not require mapping + // SendDataResult to RTCError and back again. + switch (result) { + case cricket::SendDataResult::SDR_SUCCESS: + return RTCError::OK(); + case cricket::SendDataResult::SDR_BLOCK: + // Send buffer is full. + return RTCError(RTCErrorType::RESOURCE_EXHAUSTED); + case cricket::SendDataResult::SDR_ERROR: + return RTCError(RTCErrorType::NETWORK_ERROR); + } + return RTCError(RTCErrorType::NETWORK_ERROR); +} + +RTCError SctpTransport::CloseChannel(int channel_id) { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_DCHECK(internal_sctp_transport_); + internal_sctp_transport_->ResetStream(channel_id); + return RTCError::OK(); +} + +void SctpTransport::SetDataSink(DataChannelSink* sink) { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_DCHECK(internal_sctp_transport_); + internal_sctp_transport_->SetDataChannelSink(sink); +} + +bool SctpTransport::IsReadyToSend() const { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_DCHECK(internal_sctp_transport_); + return internal_sctp_transport_->ReadyToSendData(); +} + +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()); + // 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(); + dtls_transport_ = transport; + if (internal_sctp_transport_) { + if (transport) { + internal_sctp_transport_->SetDtlsTransport(transport->internal()); + + transport->internal()->SubscribeDtlsTransportState( + [this](cricket::DtlsTransportInternal* transport, + DtlsTransportState state) { + OnDtlsStateChange(transport, state); + }); + if (info_.state() == SctpTransportState::kNew) { + next_state = SctpTransportState::kConnecting; + } + } else { + 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_); + info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(), + max_message_size, info_.MaxChannels()); + + if (!internal()->Start(local_port, remote_port, max_message_size)) { + RTC_LOG(LS_ERROR) << "Failed to push down SCTP parameters, closing."; + UpdateInformation(SctpTransportState::kClosed); + } +} + +void SctpTransport::UpdateInformation(SctpTransportState state) { + RTC_DCHECK_RUN_ON(owner_thread_); + bool 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_) { + info_ = SctpTransportInformation( + state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels()); + } else { + info_ = SctpTransportInformation( + state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels()); + } + + if (observer_ && must_send_update) { + observer_->OnStateChange(info_); + } +} + +void SctpTransport::OnAssociationChangeCommunicationUp() { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_DCHECK(internal_sctp_transport_); + if (internal_sctp_transport_->max_outbound_streams() && + internal_sctp_transport_->max_inbound_streams()) { + int max_channels = + std::min(*(internal_sctp_transport_->max_outbound_streams()), + *(internal_sctp_transport_->max_inbound_streams())); + // Record max channels. + info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(), + info_.MaxMessageSize(), max_channels); + } + + UpdateInformation(SctpTransportState::kConnected); +} + +void SctpTransport::OnDtlsStateChange(cricket::DtlsTransportInternal* transport, + DtlsTransportState state) { + RTC_DCHECK_RUN_ON(owner_thread_); + RTC_CHECK(transport == dtls_transport_->internal()); + if (state == DtlsTransportState::kClosed || + state == DtlsTransportState::kFailed) { + UpdateInformation(SctpTransportState::kClosed); + // TODO(http://bugs.webrtc.org/11090): Close all the data channels + } +} + +} // namespace webrtc |