blob: 6c4a8bea9cdffc5e0227a88a049f7e1fbf52ae7b [file] [log] [blame]
Harald Alvestrandc85328f2019-02-28 07:51:00 +01001/*
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 10:52:59 +020013#include <algorithm>
Harald Alvestrandc85328f2019-02-28 07:51:00 +010014#include <utility>
15
16namespace webrtc {
17
18SctpTransport::SctpTransport(
19 std::unique_ptr<cricket::SctpTransportInternal> internal)
20 : owner_thread_(rtc::Thread::Current()),
21 info_(SctpTransportState::kNew),
22 internal_sctp_transport_(std::move(internal)) {
23 RTC_DCHECK(internal_sctp_transport_.get());
Harald Alvestrand97716c02019-05-21 10:52:59 +020024 internal_sctp_transport_->SignalAssociationChangeCommunicationUp.connect(
25 this, &SctpTransport::OnAssociationChangeCommunicationUp);
Harald Alvestrandc85328f2019-02-28 07:51:00 +010026 // TODO(https://bugs.webrtc.org/10360): Add handlers for transport closing.
27
28 if (dtls_transport_) {
29 UpdateInformation(SctpTransportState::kConnecting);
30 } else {
31 UpdateInformation(SctpTransportState::kNew);
32 }
33}
34
35SctpTransport::~SctpTransport() {
36 // We depend on the network thread to call Clear() before dropping
37 // its last reference to this object.
38 RTC_DCHECK(owner_thread_->IsCurrent() || !internal_sctp_transport_);
39}
40
41SctpTransportInformation SctpTransport::Information() const {
42 rtc::CritScope scope(&lock_);
43 return info_;
44}
45
46void SctpTransport::RegisterObserver(SctpTransportObserverInterface* observer) {
47 RTC_DCHECK_RUN_ON(owner_thread_);
48 RTC_DCHECK(observer);
49 RTC_DCHECK(!observer_);
50 observer_ = observer;
51}
52
53void SctpTransport::UnregisterObserver() {
54 RTC_DCHECK_RUN_ON(owner_thread_);
55 observer_ = nullptr;
56}
57
58rtc::scoped_refptr<DtlsTransportInterface> SctpTransport::dtls_transport()
59 const {
60 RTC_DCHECK_RUN_ON(owner_thread_);
61 return dtls_transport_;
62}
63
64// Internal functions
65void SctpTransport::Clear() {
66 RTC_DCHECK_RUN_ON(owner_thread_);
67 RTC_DCHECK(internal());
68 {
69 rtc::CritScope scope(&lock_);
70 // Note that we delete internal_sctp_transport_, but
71 // only drop the reference to dtls_transport_.
72 dtls_transport_ = nullptr;
73 internal_sctp_transport_ = nullptr;
74 }
75 UpdateInformation(SctpTransportState::kClosed);
76}
77
78void SctpTransport::SetDtlsTransport(
79 rtc::scoped_refptr<DtlsTransport> transport) {
80 RTC_DCHECK_RUN_ON(owner_thread_);
Harald Alvestrandd61f2a72019-05-08 20:20:59 +020081 SctpTransportState next_state;
82 {
83 rtc::CritScope scope(&lock_);
84 next_state = info_.state();
85 dtls_transport_ = transport;
86 if (internal_sctp_transport_) {
87 if (transport) {
88 internal_sctp_transport_->SetDtlsTransport(transport->internal());
89 if (info_.state() == SctpTransportState::kNew) {
90 next_state = SctpTransportState::kConnecting;
91 }
92 } else {
93 internal_sctp_transport_->SetDtlsTransport(nullptr);
Harald Alvestrandc85328f2019-02-28 07:51:00 +010094 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010095 }
96 }
Harald Alvestrandd61f2a72019-05-08 20:20:59 +020097 UpdateInformation(next_state);
Harald Alvestrandc85328f2019-02-28 07:51:00 +010098}
99
Harald Alvestrand8d3d6cf2019-05-16 11:49:17 +0200100void SctpTransport::Start(int local_port,
101 int remote_port,
102 int max_message_size) {
103 {
104 rtc::CritScope scope(&lock_);
105 // Record max message size on calling thread.
106 info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
107 max_message_size, info_.MaxChannels());
108 }
109 if (owner_thread_->IsCurrent()) {
110 if (!internal()->Start(local_port, remote_port, max_message_size)) {
111 RTC_LOG(LS_ERROR) << "Failed to push down SCTP parameters, closing.";
112 UpdateInformation(SctpTransportState::kClosed);
113 }
114 } else {
115 owner_thread_->Invoke<void>(
116 RTC_FROM_HERE, rtc::Bind(&SctpTransport::Start, this, local_port,
117 remote_port, max_message_size));
118 }
119}
120
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100121void SctpTransport::UpdateInformation(SctpTransportState state) {
122 RTC_DCHECK_RUN_ON(owner_thread_);
123 bool must_send_update;
124 SctpTransportInformation info_copy(SctpTransportState::kNew);
125 {
126 rtc::CritScope scope(&lock_);
127 must_send_update = (state != info_.state());
Harald Alvestrand8d3d6cf2019-05-16 11:49:17 +0200128 // TODO(https://bugs.webrtc.org/10358): Update max channels from internal
129 // SCTP transport when available.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200130 if (internal_sctp_transport_) {
131 info_ = SctpTransportInformation(
Harald Alvestrand8d3d6cf2019-05-16 11:49:17 +0200132 state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200133 } else {
134 info_ = SctpTransportInformation(
135 state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
136 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100137 if (observer_ && must_send_update) {
138 info_copy = info_;
139 }
140 }
141 // We call the observer without holding the lock.
142 if (observer_ && must_send_update) {
143 observer_->OnStateChange(info_copy);
144 }
145}
146
Harald Alvestrand97716c02019-05-21 10:52:59 +0200147void SctpTransport::OnAssociationChangeCommunicationUp() {
148 RTC_DCHECK_RUN_ON(owner_thread_);
149 {
150 rtc::CritScope scope(&lock_);
151 RTC_DCHECK(internal_sctp_transport_);
152 if (internal_sctp_transport_->max_outbound_streams() &&
153 internal_sctp_transport_->max_inbound_streams()) {
154 int max_channels =
155 std::min(*(internal_sctp_transport_->max_outbound_streams()),
156 *(internal_sctp_transport_->max_inbound_streams()));
157 // Record max channels.
158 info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
159 info_.MaxMessageSize(), max_channels);
160 }
161 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100162 UpdateInformation(SctpTransportState::kConnected);
163}
164
165} // namespace webrtc