blob: 7d4e4551f1841ae725f3b5e95c9542589cd33e72 [file] [log] [blame]
Harald Alvestrandc85328f2019-02-28 06:51:001/*
2 * Copyright 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "pc/sctp_transport.h"
12
Harald Alvestrand97716c02019-05-21 08:52:5913#include <algorithm>
Harald Alvestrandc85328f2019-02-28 06:51:0014#include <utility>
15
Harald Alvestrand5761e7b2021-01-29 14:45:0816#include "absl/types/optional.h"
Mirko Bonadei9f6808b2021-05-21 18:46:0917#include "api/dtls_transport_interface.h"
Artem Titovd15a5752021-02-10 13:31:2418#include "api/sequence_checker.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0819#include "rtc_base/checks.h"
20#include "rtc_base/location.h"
21#include "rtc_base/logging.h"
Harald Alvestrand5761e7b2021-01-29 14:45:0822
Harald Alvestrandc85328f2019-02-28 06:51:0023namespace webrtc {
24
25SctpTransport::SctpTransport(
26 std::unique_ptr<cricket::SctpTransportInternal> internal)
27 : owner_thread_(rtc::Thread::Current()),
28 info_(SctpTransportState::kNew),
29 internal_sctp_transport_(std::move(internal)) {
30 RTC_DCHECK(internal_sctp_transport_.get());
Harald Alvestrand97716c02019-05-21 08:52:5931 internal_sctp_transport_->SignalAssociationChangeCommunicationUp.connect(
32 this, &SctpTransport::OnAssociationChangeCommunicationUp);
Harald Alvestrandc85328f2019-02-28 06:51:0033 // TODO(https://bugs.webrtc.org/10360): Add handlers for transport closing.
34
35 if (dtls_transport_) {
36 UpdateInformation(SctpTransportState::kConnecting);
37 } else {
38 UpdateInformation(SctpTransportState::kNew);
39 }
40}
41
42SctpTransport::~SctpTransport() {
43 // We depend on the network thread to call Clear() before dropping
44 // its last reference to this object.
45 RTC_DCHECK(owner_thread_->IsCurrent() || !internal_sctp_transport_);
46}
47
48SctpTransportInformation SctpTransport::Information() const {
Tomas Gunnarsson92eebef2021-02-10 12:05:4449 // TODO(tommi): Update PeerConnection::GetSctpTransport to hand out a proxy
50 // to the transport so that we can be sure that methods get called on the
51 // expected thread. Chromium currently calls this method from
52 // TransceiverStateSurfacer.
53 if (!owner_thread_->IsCurrent()) {
54 return owner_thread_->Invoke<SctpTransportInformation>(
55 RTC_FROM_HERE, [this] { return Information(); });
56 }
57 RTC_DCHECK_RUN_ON(owner_thread_);
Harald Alvestrandc85328f2019-02-28 06:51:0058 return info_;
59}
60
61void SctpTransport::RegisterObserver(SctpTransportObserverInterface* observer) {
62 RTC_DCHECK_RUN_ON(owner_thread_);
63 RTC_DCHECK(observer);
64 RTC_DCHECK(!observer_);
65 observer_ = observer;
66}
67
68void SctpTransport::UnregisterObserver() {
69 RTC_DCHECK_RUN_ON(owner_thread_);
70 observer_ = nullptr;
71}
72
73rtc::scoped_refptr<DtlsTransportInterface> SctpTransport::dtls_transport()
74 const {
75 RTC_DCHECK_RUN_ON(owner_thread_);
76 return dtls_transport_;
77}
78
79// Internal functions
80void SctpTransport::Clear() {
81 RTC_DCHECK_RUN_ON(owner_thread_);
82 RTC_DCHECK(internal());
Tomas Gunnarsson92eebef2021-02-10 12:05:4483 // Note that we delete internal_sctp_transport_, but
84 // only drop the reference to dtls_transport_.
85 dtls_transport_ = nullptr;
86 internal_sctp_transport_ = nullptr;
Harald Alvestrandc85328f2019-02-28 06:51:0087 UpdateInformation(SctpTransportState::kClosed);
88}
89
90void SctpTransport::SetDtlsTransport(
91 rtc::scoped_refptr<DtlsTransport> transport) {
92 RTC_DCHECK_RUN_ON(owner_thread_);
Tomas Gunnarsson92eebef2021-02-10 12:05:4493 SctpTransportState next_state = info_.state();
94 dtls_transport_ = transport;
95 if (internal_sctp_transport_) {
96 if (transport) {
97 internal_sctp_transport_->SetDtlsTransport(transport->internal());
Lahiru Ginnaliya Gamathige60c0b442021-02-16 15:29:0898
Mirko Bonadei9f6808b2021-05-21 18:46:0999 transport->internal()->SubscribeDtlsTransportState(
Lahiru Ginnaliya Gamathige60c0b442021-02-16 15:29:08100 [this](cricket::DtlsTransportInternal* transport,
Mirko Bonadei9f6808b2021-05-21 18:46:09101 DtlsTransportState state) {
Lahiru Ginnaliya Gamathige60c0b442021-02-16 15:29:08102 OnDtlsStateChange(transport, state);
103 });
Tomas Gunnarsson92eebef2021-02-10 12:05:44104 if (info_.state() == SctpTransportState::kNew) {
105 next_state = SctpTransportState::kConnecting;
Harald Alvestrandc85328f2019-02-28 06:51:00106 }
Tomas Gunnarsson92eebef2021-02-10 12:05:44107 } else {
108 internal_sctp_transport_->SetDtlsTransport(nullptr);
Harald Alvestrandc85328f2019-02-28 06:51:00109 }
110 }
Tomas Gunnarsson92eebef2021-02-10 12:05:44111
Harald Alvestrandd61f2a72019-05-08 18:20:59112 UpdateInformation(next_state);
Harald Alvestrandc85328f2019-02-28 06:51:00113}
114
Harald Alvestrand8d3d6cf2019-05-16 09:49:17115void SctpTransport::Start(int local_port,
116 int remote_port,
117 int max_message_size) {
Tomas Gunnarsson92eebef2021-02-10 12:05:44118 RTC_DCHECK_RUN_ON(owner_thread_);
119 info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
120 max_message_size, info_.MaxChannels());
121
122 if (!internal()->Start(local_port, remote_port, max_message_size)) {
123 RTC_LOG(LS_ERROR) << "Failed to push down SCTP parameters, closing.";
124 UpdateInformation(SctpTransportState::kClosed);
Harald Alvestrand8d3d6cf2019-05-16 09:49:17125 }
126}
127
Harald Alvestrandc85328f2019-02-28 06:51:00128void SctpTransport::UpdateInformation(SctpTransportState state) {
129 RTC_DCHECK_RUN_ON(owner_thread_);
Tomas Gunnarsson92eebef2021-02-10 12:05:44130 bool must_send_update = (state != info_.state());
131 // TODO(https://bugs.webrtc.org/10358): Update max channels from internal
132 // SCTP transport when available.
133 if (internal_sctp_transport_) {
134 info_ = SctpTransportInformation(
135 state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
136 } else {
137 info_ = SctpTransportInformation(
138 state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
Harald Alvestrandc85328f2019-02-28 06:51:00139 }
Tomas Gunnarsson92eebef2021-02-10 12:05:44140
Harald Alvestrandc85328f2019-02-28 06:51:00141 if (observer_ && must_send_update) {
Tomas Gunnarsson92eebef2021-02-10 12:05:44142 observer_->OnStateChange(info_);
Harald Alvestrandc85328f2019-02-28 06:51:00143 }
144}
145
Harald Alvestrand97716c02019-05-21 08:52:59146void SctpTransport::OnAssociationChangeCommunicationUp() {
147 RTC_DCHECK_RUN_ON(owner_thread_);
Tomas Gunnarsson92eebef2021-02-10 12:05:44148 RTC_DCHECK(internal_sctp_transport_);
149 if (internal_sctp_transport_->max_outbound_streams() &&
150 internal_sctp_transport_->max_inbound_streams()) {
151 int max_channels =
152 std::min(*(internal_sctp_transport_->max_outbound_streams()),
153 *(internal_sctp_transport_->max_inbound_streams()));
154 // Record max channels.
155 info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
156 info_.MaxMessageSize(), max_channels);
Harald Alvestrand97716c02019-05-21 08:52:59157 }
Tomas Gunnarsson92eebef2021-02-10 12:05:44158
Harald Alvestrandc85328f2019-02-28 06:51:00159 UpdateInformation(SctpTransportState::kConnected);
160}
161
Harald Alvestrand408cb4b2019-11-16 11:09:08162void SctpTransport::OnDtlsStateChange(cricket::DtlsTransportInternal* transport,
Mirko Bonadei9f6808b2021-05-21 18:46:09163 DtlsTransportState state) {
Harald Alvestrand408cb4b2019-11-16 11:09:08164 RTC_DCHECK_RUN_ON(owner_thread_);
165 RTC_CHECK(transport == dtls_transport_->internal());
Mirko Bonadei9f6808b2021-05-21 18:46:09166 if (state == DtlsTransportState::kClosed ||
167 state == DtlsTransportState::kFailed) {
Harald Alvestrand408cb4b2019-11-16 11:09:08168 UpdateInformation(SctpTransportState::kClosed);
169 // TODO(http://bugs.webrtc.org/11090): Close all the data channels
170 }
171}
172
Harald Alvestrandc85328f2019-02-28 06:51:00173} // namespace webrtc