blob: 5470b5b82e655e3643bee0ed9f42eb9eb706578a [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2004 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "p2p/base/portallocator.h"
Steve Anton6c38cc72017-11-29 10:25:58 -080012
13#include <utility>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/checks.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000016
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000017namespace cricket {
18
Steve Anton7995d8c2017-10-30 16:23:38 -070019RelayServerConfig::RelayServerConfig(RelayType type) : type(type) {}
20
21RelayServerConfig::RelayServerConfig(const rtc::SocketAddress& address,
22 const std::string& username,
23 const std::string& password,
24 ProtocolType proto)
25 : type(RELAY_TURN), credentials(username, password) {
26 ports.push_back(ProtocolAddress(address, proto));
27}
28
29RelayServerConfig::RelayServerConfig(const std::string& address,
30 int port,
31 const std::string& username,
32 const std::string& password,
33 ProtocolType proto)
34 : RelayServerConfig(rtc::SocketAddress(address, port),
35 username,
36 password,
37 proto) {}
38
39// Legacy constructor where "secure" and PROTO_TCP implies PROTO_TLS.
40RelayServerConfig::RelayServerConfig(const std::string& address,
41 int port,
42 const std::string& username,
43 const std::string& password,
44 ProtocolType proto,
45 bool secure)
46 : RelayServerConfig(address,
47 port,
48 username,
49 password,
50 (proto == PROTO_TCP && secure ? PROTO_TLS : proto)) {}
51
52RelayServerConfig::RelayServerConfig(const RelayServerConfig&) = default;
53
54RelayServerConfig::~RelayServerConfig() = default;
55
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056PortAllocatorSession::PortAllocatorSession(const std::string& content_name,
57 int component,
58 const std::string& ice_ufrag,
59 const std::string& ice_pwd,
Peter Boström0c4e06b2015-10-07 12:23:21 +020060 uint32_t flags)
Taylor Brandstettera1c30352016-05-13 08:15:11 -070061 : flags_(flags),
deadbeefc55fb302016-05-12 12:51:38 -070062 generation_(0),
Taylor Brandstettera1c30352016-05-13 08:15:11 -070063 content_name_(content_name),
64 component_(component),
deadbeefcbecd352015-09-23 11:50:27 -070065 ice_ufrag_(ice_ufrag),
66 ice_pwd_(ice_pwd) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -070067 // Pooled sessions are allowed to be created with empty content name,
68 // component, ufrag and password.
69 RTC_DCHECK(ice_ufrag.empty() == ice_pwd.empty());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000070}
71
Steve Anton7995d8c2017-10-30 16:23:38 -070072PortAllocatorSession::~PortAllocatorSession() = default;
73
74bool PortAllocatorSession::IsCleared() const {
75 return false;
76}
77
78bool PortAllocatorSession::IsStopped() const {
79 return false;
80}
81
Qingsi Wang72a43a12018-02-20 16:03:18 -080082void PortAllocatorSession::GetCandidateStatsFromReadyPorts(
83 CandidateStatsList* candidate_stats_list) const {
84 auto ports = ReadyPorts();
85 for (auto* port : ports) {
86 auto candidates = port->Candidates();
87 for (const auto& candidate : candidates) {
88 CandidateStats candidate_stats(candidate);
89 port->GetStunStats(&candidate_stats.stun_stats);
90 candidate_stats_list->push_back(std::move(candidate_stats));
91 }
92 }
93}
94
Steve Anton7995d8c2017-10-30 16:23:38 -070095uint32_t PortAllocatorSession::generation() {
96 return generation_;
97}
98
99void PortAllocatorSession::set_generation(uint32_t generation) {
100 generation_ = generation;
101}
102
103PortAllocator::PortAllocator()
104 : flags_(kDefaultPortAllocatorFlags),
105 min_port_(0),
106 max_port_(0),
107 max_ipv6_networks_(kDefaultMaxIPv6Networks),
108 step_delay_(kDefaultStepDelay),
109 allow_tcp_listen_(true),
Qingsi Wanga2d60672018-04-11 16:57:45 -0700110 candidate_filter_(CF_ALL) {
111 // The allocator will be attached to a thread in Initialize.
112 thread_checker_.DetachFromThread();
113}
Steve Anton7995d8c2017-10-30 16:23:38 -0700114
Qingsi Wanga2d60672018-04-11 16:57:45 -0700115void PortAllocator::Initialize() {
116 RTC_DCHECK(thread_checker_.CalledOnValidThread());
117 initialized_ = true;
118}
119
120PortAllocator::~PortAllocator() {
121 CheckRunOnValidThreadIfInitialized();
122}
Steve Anton7995d8c2017-10-30 16:23:38 -0700123
deadbeef6de92f92016-12-12 18:49:32 -0800124bool PortAllocator::SetConfiguration(
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700125 const ServerAddresses& stun_servers,
126 const std::vector<RelayServerConfig>& turn_servers,
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700127 int candidate_pool_size,
Jonas Orelandbdcee282017-10-10 14:01:40 +0200128 bool prune_turn_ports,
Qingsi Wangdb53f8e2018-02-20 14:45:49 -0800129 webrtc::TurnCustomizer* turn_customizer,
Danil Chapovalov00c71832018-06-15 15:58:38 +0200130 const absl::optional<int>& stun_candidate_keepalive_interval) {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700131 CheckRunOnValidThreadIfInitialized();
Qingsi Wange6ded162018-10-02 16:00:41 -0700132 // A positive candidate pool size would lead to the creation of a pooled
133 // allocator session and starting getting ports, which we should only do on
134 // the network thread.
135 RTC_DCHECK(candidate_pool_size == 0 || thread_checker_.CalledOnValidThread());
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700136 bool ice_servers_changed =
137 (stun_servers != stun_servers_ || turn_servers != turn_servers_);
138 stun_servers_ = stun_servers;
139 turn_servers_ = turn_servers;
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700140 prune_turn_ports_ = prune_turn_ports;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700141
deadbeef42a42632017-03-10 15:18:00 -0800142 if (candidate_pool_frozen_) {
143 if (candidate_pool_size != candidate_pool_size_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100144 RTC_LOG(LS_ERROR)
Jonas Olssond7d762d2018-03-28 09:47:51 +0200145 << "Trying to change candidate pool size after pool was frozen.";
deadbeef42a42632017-03-10 15:18:00 -0800146 return false;
147 }
148 return true;
deadbeef6de92f92016-12-12 18:49:32 -0800149 }
deadbeef42a42632017-03-10 15:18:00 -0800150
deadbeef6de92f92016-12-12 18:49:32 -0800151 if (candidate_pool_size < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_ERROR) << "Can't set negative pool size.";
deadbeef6de92f92016-12-12 18:49:32 -0800153 return false;
154 }
deadbeef6de92f92016-12-12 18:49:32 -0800155
deadbeef42a42632017-03-10 15:18:00 -0800156 candidate_pool_size_ = candidate_pool_size;
deadbeef6de92f92016-12-12 18:49:32 -0800157
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700158 // If ICE servers changed, throw away any existing pooled sessions and create
159 // new ones.
160 if (ice_servers_changed) {
161 pooled_sessions_.clear();
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700162 }
163
Jonas Orelandbdcee282017-10-10 14:01:40 +0200164 turn_customizer_ = turn_customizer;
165
deadbeef42a42632017-03-10 15:18:00 -0800166 // If |candidate_pool_size_| is less than the number of pooled sessions, get
167 // rid of the extras.
168 while (candidate_pool_size_ < static_cast<int>(pooled_sessions_.size())) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700169 pooled_sessions_.front().reset(nullptr);
170 pooled_sessions_.pop_front();
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700171 }
deadbeef6de92f92016-12-12 18:49:32 -0800172
Qingsi Wangdb53f8e2018-02-20 14:45:49 -0800173 // |stun_candidate_keepalive_interval_| will be used in STUN port allocation
174 // in future sessions. We also update the ready ports in the pooled sessions.
175 // Ports in sessions that are taken and owned by P2PTransportChannel will be
176 // updated there via IceConfig.
177 stun_candidate_keepalive_interval_ = stun_candidate_keepalive_interval;
178 for (const auto& session : pooled_sessions_) {
179 session->SetStunKeepaliveIntervalForReadyPorts(
180 stun_candidate_keepalive_interval_);
181 }
182
deadbeef42a42632017-03-10 15:18:00 -0800183 // If |candidate_pool_size_| is greater than the number of pooled sessions,
deadbeef6de92f92016-12-12 18:49:32 -0800184 // create new sessions.
deadbeef42a42632017-03-10 15:18:00 -0800185 while (static_cast<int>(pooled_sessions_.size()) < candidate_pool_size_) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700186 PortAllocatorSession* pooled_session = CreateSessionInternal("", 0, "", "");
187 pooled_session->StartGettingPorts();
188 pooled_sessions_.push_back(
189 std::unique_ptr<PortAllocatorSession>(pooled_session));
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700190 }
deadbeef6de92f92016-12-12 18:49:32 -0800191 return true;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700192}
193
194std::unique_ptr<PortAllocatorSession> PortAllocator::CreateSession(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000195 const std::string& content_name,
196 int component,
197 const std::string& ice_ufrag,
198 const std::string& ice_pwd) {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700199 CheckRunOnValidThreadAndInitialized();
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700200 auto session = std::unique_ptr<PortAllocatorSession>(
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700201 CreateSessionInternal(content_name, component, ice_ufrag, ice_pwd));
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700202 session->SetCandidateFilter(candidate_filter());
203 return session;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700204}
205
206std::unique_ptr<PortAllocatorSession> PortAllocator::TakePooledSession(
207 const std::string& content_name,
208 int component,
209 const std::string& ice_ufrag,
210 const std::string& ice_pwd) {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700211 CheckRunOnValidThreadAndInitialized();
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700212 RTC_DCHECK(!ice_ufrag.empty());
213 RTC_DCHECK(!ice_pwd.empty());
214 if (pooled_sessions_.empty()) {
215 return nullptr;
216 }
217 std::unique_ptr<PortAllocatorSession> ret =
218 std::move(pooled_sessions_.front());
219 ret->SetIceParameters(content_name, component, ice_ufrag, ice_pwd);
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700220 // According to JSEP, a pooled session should filter candidates only after
221 // it's taken out of the pool.
222 ret->SetCandidateFilter(candidate_filter());
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700223 pooled_sessions_.pop_front();
224 return ret;
225}
226
227const PortAllocatorSession* PortAllocator::GetPooledSession() const {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700228 CheckRunOnValidThreadAndInitialized();
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700229 if (pooled_sessions_.empty()) {
230 return nullptr;
231 }
232 return pooled_sessions_.front().get();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000233}
234
deadbeef42a42632017-03-10 15:18:00 -0800235void PortAllocator::FreezeCandidatePool() {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700236 CheckRunOnValidThreadAndInitialized();
deadbeef42a42632017-03-10 15:18:00 -0800237 candidate_pool_frozen_ = true;
238}
239
240void PortAllocator::DiscardCandidatePool() {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700241 CheckRunOnValidThreadIfInitialized();
deadbeef42a42632017-03-10 15:18:00 -0800242 pooled_sessions_.clear();
243}
244
Qingsi Wang72a43a12018-02-20 16:03:18 -0800245void PortAllocator::GetCandidateStatsFromPooledSessions(
246 CandidateStatsList* candidate_stats_list) {
Qingsi Wanga2d60672018-04-11 16:57:45 -0700247 CheckRunOnValidThreadAndInitialized();
Qingsi Wang72a43a12018-02-20 16:03:18 -0800248 for (const auto& session : pooled_sessions()) {
249 session->GetCandidateStatsFromReadyPorts(candidate_stats_list);
250 }
251}
252
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000253} // namespace cricket