blob: 1c0289a940cc40d87312a21526430ad778493d3b [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
13#include <utility>
14
15namespace webrtc {
16
17SctpTransport::SctpTransport(
18 std::unique_ptr<cricket::SctpTransportInternal> internal)
19 : owner_thread_(rtc::Thread::Current()),
20 info_(SctpTransportState::kNew),
21 internal_sctp_transport_(std::move(internal)) {
22 RTC_DCHECK(internal_sctp_transport_.get());
23 internal_sctp_transport_->SignalReadyToSendData.connect(
24 this, &SctpTransport::OnInternalReadyToSendData);
25 // TODO(https://bugs.webrtc.org/10360): Add handlers for transport closing.
26
27 if (dtls_transport_) {
28 UpdateInformation(SctpTransportState::kConnecting);
29 } else {
30 UpdateInformation(SctpTransportState::kNew);
31 }
32}
33
34SctpTransport::~SctpTransport() {
35 // We depend on the network thread to call Clear() before dropping
36 // its last reference to this object.
37 RTC_DCHECK(owner_thread_->IsCurrent() || !internal_sctp_transport_);
38}
39
40SctpTransportInformation SctpTransport::Information() const {
41 rtc::CritScope scope(&lock_);
42 return info_;
43}
44
45void SctpTransport::RegisterObserver(SctpTransportObserverInterface* observer) {
46 RTC_DCHECK_RUN_ON(owner_thread_);
47 RTC_DCHECK(observer);
48 RTC_DCHECK(!observer_);
49 observer_ = observer;
50}
51
52void SctpTransport::UnregisterObserver() {
53 RTC_DCHECK_RUN_ON(owner_thread_);
54 observer_ = nullptr;
55}
56
57rtc::scoped_refptr<DtlsTransportInterface> SctpTransport::dtls_transport()
58 const {
59 RTC_DCHECK_RUN_ON(owner_thread_);
60 return dtls_transport_;
61}
62
63// Internal functions
64void SctpTransport::Clear() {
65 RTC_DCHECK_RUN_ON(owner_thread_);
66 RTC_DCHECK(internal());
67 {
68 rtc::CritScope scope(&lock_);
69 // Note that we delete internal_sctp_transport_, but
70 // only drop the reference to dtls_transport_.
71 dtls_transport_ = nullptr;
72 internal_sctp_transport_ = nullptr;
73 }
74 UpdateInformation(SctpTransportState::kClosed);
75}
76
77void SctpTransport::SetDtlsTransport(
78 rtc::scoped_refptr<DtlsTransport> transport) {
79 RTC_DCHECK_RUN_ON(owner_thread_);
Harald Alvestrandd61f2a72019-05-08 20:20:59 +020080 SctpTransportState next_state;
81 {
82 rtc::CritScope scope(&lock_);
83 next_state = info_.state();
84 dtls_transport_ = transport;
85 if (internal_sctp_transport_) {
86 if (transport) {
87 internal_sctp_transport_->SetDtlsTransport(transport->internal());
88 if (info_.state() == SctpTransportState::kNew) {
89 next_state = SctpTransportState::kConnecting;
90 }
91 } else {
92 internal_sctp_transport_->SetDtlsTransport(nullptr);
Harald Alvestrandc85328f2019-02-28 07:51:00 +010093 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +010094 }
95 }
Harald Alvestrandd61f2a72019-05-08 20:20:59 +020096 UpdateInformation(next_state);
Harald Alvestrandc85328f2019-02-28 07:51:00 +010097}
98
Harald Alvestrand8d3d6cf2019-05-16 11:49:17 +020099void SctpTransport::Start(int local_port,
100 int remote_port,
101 int max_message_size) {
102 {
103 rtc::CritScope scope(&lock_);
104 // Record max message size on calling thread.
105 info_ = SctpTransportInformation(info_.state(), info_.dtls_transport(),
106 max_message_size, info_.MaxChannels());
107 }
108 if (owner_thread_->IsCurrent()) {
109 if (!internal()->Start(local_port, remote_port, max_message_size)) {
110 RTC_LOG(LS_ERROR) << "Failed to push down SCTP parameters, closing.";
111 UpdateInformation(SctpTransportState::kClosed);
112 }
113 } else {
114 owner_thread_->Invoke<void>(
115 RTC_FROM_HERE, rtc::Bind(&SctpTransport::Start, this, local_port,
116 remote_port, max_message_size));
117 }
118}
119
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100120void SctpTransport::UpdateInformation(SctpTransportState state) {
121 RTC_DCHECK_RUN_ON(owner_thread_);
122 bool must_send_update;
123 SctpTransportInformation info_copy(SctpTransportState::kNew);
124 {
125 rtc::CritScope scope(&lock_);
126 must_send_update = (state != info_.state());
Harald Alvestrand8d3d6cf2019-05-16 11:49:17 +0200127 // TODO(https://bugs.webrtc.org/10358): Update max channels from internal
128 // SCTP transport when available.
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200129 if (internal_sctp_transport_) {
130 info_ = SctpTransportInformation(
Harald Alvestrand8d3d6cf2019-05-16 11:49:17 +0200131 state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
Harald Alvestrandfbb45bd2019-05-15 08:07:47 +0200132 } else {
133 info_ = SctpTransportInformation(
134 state, dtls_transport_, info_.MaxMessageSize(), info_.MaxChannels());
135 }
Harald Alvestrandc85328f2019-02-28 07:51:00 +0100136 if (observer_ && must_send_update) {
137 info_copy = info_;
138 }
139 }
140 // We call the observer without holding the lock.
141 if (observer_ && must_send_update) {
142 observer_->OnStateChange(info_copy);
143 }
144}
145
146void SctpTransport::OnInternalReadyToSendData() {
147 UpdateInformation(SctpTransportState::kConnected);
148}
149
150} // namespace webrtc