blob: e39a44013cdcf4f5b4cf627e225c499afb1e1687 [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
11#include "webrtc/p2p/client/basicportallocator.h"
12
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080013#include <algorithm>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000014#include <string>
15#include <vector>
16
17#include "webrtc/p2p/base/basicpacketsocketfactory.h"
18#include "webrtc/p2p/base/common.h"
19#include "webrtc/p2p/base/port.h"
20#include "webrtc/p2p/base/relayport.h"
21#include "webrtc/p2p/base/stunport.h"
22#include "webrtc/p2p/base/tcpport.h"
23#include "webrtc/p2p/base/turnport.h"
24#include "webrtc/p2p/base/udpport.h"
Guo-wei Shieh38f88932015-08-13 22:24:02 -070025#include "webrtc/base/checks.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000026#include "webrtc/base/common.h"
27#include "webrtc/base/helpers.h"
28#include "webrtc/base/logging.h"
29
30using rtc::CreateRandomId;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000031
32namespace {
33
34enum {
35 MSG_CONFIG_START,
36 MSG_CONFIG_READY,
37 MSG_ALLOCATE,
38 MSG_ALLOCATION_PHASE,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000039 MSG_SEQUENCEOBJECTS_CREATED,
40 MSG_CONFIG_STOP,
41};
42
43const int PHASE_UDP = 0;
44const int PHASE_RELAY = 1;
45const int PHASE_TCP = 2;
46const int PHASE_SSLTCP = 3;
47
48const int kNumPhases = 4;
49
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050} // namespace
51
52namespace cricket {
Peter Boström0c4e06b2015-10-07 12:23:21 +020053const uint32_t DISABLE_ALL_PHASES =
honghaizf421bdc2015-07-17 16:21:55 -070054 PORTALLOCATOR_DISABLE_UDP | PORTALLOCATOR_DISABLE_TCP |
55 PORTALLOCATOR_DISABLE_STUN | PORTALLOCATOR_DISABLE_RELAY;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056
57// BasicPortAllocator
Taylor Brandstettera1c30352016-05-13 08:15:11 -070058BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager,
59 rtc::PacketSocketFactory* socket_factory)
60 : network_manager_(network_manager), socket_factory_(socket_factory) {
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080061 ASSERT(network_manager_ != nullptr);
62 ASSERT(socket_factory_ != nullptr);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000063 Construct();
64}
65
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080066BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager)
Taylor Brandstettera1c30352016-05-13 08:15:11 -070067 : network_manager_(network_manager), socket_factory_(nullptr) {
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080068 ASSERT(network_manager_ != nullptr);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000069 Construct();
70}
71
Taylor Brandstettera1c30352016-05-13 08:15:11 -070072BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager,
73 rtc::PacketSocketFactory* socket_factory,
74 const ServerAddresses& stun_servers)
75 : network_manager_(network_manager), socket_factory_(socket_factory) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000076 ASSERT(socket_factory_ != NULL);
Taylor Brandstettera1c30352016-05-13 08:15:11 -070077 SetConfiguration(stun_servers, std::vector<RelayServerConfig>(), 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000078 Construct();
79}
80
81BasicPortAllocator::BasicPortAllocator(
82 rtc::NetworkManager* network_manager,
83 const ServerAddresses& stun_servers,
84 const rtc::SocketAddress& relay_address_udp,
85 const rtc::SocketAddress& relay_address_tcp,
86 const rtc::SocketAddress& relay_address_ssl)
Taylor Brandstettera1c30352016-05-13 08:15:11 -070087 : network_manager_(network_manager), socket_factory_(NULL) {
88 std::vector<RelayServerConfig> turn_servers;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000089 RelayServerConfig config(RELAY_GTURN);
deadbeef653b8e02015-11-11 12:55:10 -080090 if (!relay_address_udp.IsNil()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000091 config.ports.push_back(ProtocolAddress(relay_address_udp, PROTO_UDP));
deadbeef653b8e02015-11-11 12:55:10 -080092 }
93 if (!relay_address_tcp.IsNil()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000094 config.ports.push_back(ProtocolAddress(relay_address_tcp, PROTO_TCP));
deadbeef653b8e02015-11-11 12:55:10 -080095 }
96 if (!relay_address_ssl.IsNil()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000097 config.ports.push_back(ProtocolAddress(relay_address_ssl, PROTO_SSLTCP));
deadbeef653b8e02015-11-11 12:55:10 -080098 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000099
deadbeef653b8e02015-11-11 12:55:10 -0800100 if (!config.ports.empty()) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700101 turn_servers.push_back(config);
deadbeef653b8e02015-11-11 12:55:10 -0800102 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000103
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700104 SetConfiguration(stun_servers, turn_servers, 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000105 Construct();
106}
107
108void BasicPortAllocator::Construct() {
109 allow_tcp_listen_ = true;
110}
111
112BasicPortAllocator::~BasicPortAllocator() {
113}
114
deadbeefc5d0d952015-07-16 10:22:21 -0700115PortAllocatorSession* BasicPortAllocator::CreateSessionInternal(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000116 const std::string& content_name, int component,
117 const std::string& ice_ufrag, const std::string& ice_pwd) {
118 return new BasicPortAllocatorSession(
119 this, content_name, component, ice_ufrag, ice_pwd);
120}
121
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700122void BasicPortAllocator::AddTurnServer(const RelayServerConfig& turn_server) {
123 std::vector<RelayServerConfig> new_turn_servers = turn_servers();
124 new_turn_servers.push_back(turn_server);
125 SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size());
126}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000127
128// BasicPortAllocatorSession
129BasicPortAllocatorSession::BasicPortAllocatorSession(
130 BasicPortAllocator *allocator,
131 const std::string& content_name,
132 int component,
133 const std::string& ice_ufrag,
134 const std::string& ice_pwd)
135 : PortAllocatorSession(content_name, component,
136 ice_ufrag, ice_pwd, allocator->flags()),
137 allocator_(allocator), network_thread_(NULL),
138 socket_factory_(allocator->socket_factory()),
139 allocation_started_(false),
140 network_manager_started_(false),
141 running_(false),
142 allocation_sequences_created_(false) {
143 allocator_->network_manager()->SignalNetworksChanged.connect(
144 this, &BasicPortAllocatorSession::OnNetworksChanged);
145 allocator_->network_manager()->StartUpdating();
146}
147
148BasicPortAllocatorSession::~BasicPortAllocatorSession() {
149 allocator_->network_manager()->StopUpdating();
150 if (network_thread_ != NULL)
151 network_thread_->Clear(this);
152
Peter Boström0c4e06b2015-10-07 12:23:21 +0200153 for (uint32_t i = 0; i < sequences_.size(); ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000154 // AllocationSequence should clear it's map entry for turn ports before
155 // ports are destroyed.
156 sequences_[i]->Clear();
157 }
158
159 std::vector<PortData>::iterator it;
160 for (it = ports_.begin(); it != ports_.end(); it++)
161 delete it->port();
162
Peter Boström0c4e06b2015-10-07 12:23:21 +0200163 for (uint32_t i = 0; i < configs_.size(); ++i)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000164 delete configs_[i];
165
Peter Boström0c4e06b2015-10-07 12:23:21 +0200166 for (uint32_t i = 0; i < sequences_.size(); ++i)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000167 delete sequences_[i];
168}
169
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700170void BasicPortAllocatorSession::SetCandidateFilter(uint32_t filter) {
171 if (filter == candidate_filter_) {
172 return;
173 }
174 // We assume the filter will only change from "ALL" to something else.
175 RTC_DCHECK(candidate_filter_ == CF_ALL);
176 candidate_filter_ = filter;
177 for (PortData& port : ports_) {
178 if (!port.has_pairable_candidate()) {
179 continue;
180 }
181 const auto& candidates = port.port()->Candidates();
182 // Setting a filter may cause a ready port to become non-ready
183 // if it no longer has any pairable candidates.
184 if (!std::any_of(candidates.begin(), candidates.end(),
185 [this, &port](const Candidate& candidate) {
186 return CandidatePairable(candidate, port.port());
187 })) {
188 port.set_has_pairable_candidate(false);
189 }
190 }
191}
192
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000193void BasicPortAllocatorSession::StartGettingPorts() {
194 network_thread_ = rtc::Thread::Current();
195 if (!socket_factory_) {
196 owned_socket_factory_.reset(
197 new rtc::BasicPacketSocketFactory(network_thread_));
198 socket_factory_ = owned_socket_factory_.get();
199 }
200
201 running_ = true;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700202 network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_START);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000203}
204
205void BasicPortAllocatorSession::StopGettingPorts() {
206 ASSERT(rtc::Thread::Current() == network_thread_);
207 running_ = false;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700208 network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_STOP);
honghaiz98db68f2015-09-29 07:58:17 -0700209 ClearGettingPorts();
210}
211
212void BasicPortAllocatorSession::ClearGettingPorts() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000213 network_thread_->Clear(this, MSG_ALLOCATE);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200214 for (uint32_t i = 0; i < sequences_.size(); ++i)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000215 sequences_[i]->Stop();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000216}
217
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700218std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
219 std::vector<PortInterface*> ret;
220 for (const PortData& port : ports_) {
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700221 if (port.has_pairable_candidate() && !port.error()) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700222 ret.push_back(port.port());
223 }
224 }
225 return ret;
226}
227
228std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
229 std::vector<Candidate> candidates;
230 for (const PortData& data : ports_) {
231 for (const Candidate& candidate : data.port()->Candidates()) {
232 if (!CheckCandidateFilter(candidate)) {
233 continue;
234 }
235 ProtocolType pvalue;
236 if (!StringToProto(candidate.protocol().c_str(), &pvalue) ||
237 !data.sequence()->ProtocolEnabled(pvalue)) {
238 continue;
239 }
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700240 candidates.push_back(SanitizeRelatedAddress(candidate));
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700241 }
242 }
243 return candidates;
244}
245
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700246Candidate BasicPortAllocatorSession::SanitizeRelatedAddress(
247 const Candidate& c) const {
248 Candidate copy = c;
249 // If adapter enumeration is disabled or host candidates are disabled,
250 // clear the raddr of STUN candidates to avoid local address leakage.
251 bool filter_stun_related_address =
252 ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
253 (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) ||
254 !(candidate_filter_ & CF_HOST);
255 // If the candidate filter doesn't allow reflexive addresses, empty TURN raddr
256 // to avoid reflexive address leakage.
257 bool filter_turn_related_address = !(candidate_filter_ & CF_REFLEXIVE);
258 if ((c.type() == STUN_PORT_TYPE && filter_stun_related_address) ||
259 (c.type() == RELAY_PORT_TYPE && filter_turn_related_address)) {
260 copy.set_related_address(
261 rtc::EmptySocketAddressWithFamily(copy.address().family()));
262 }
263 return copy;
264}
265
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700266bool BasicPortAllocatorSession::CandidatesAllocationDone() const {
267 // Done only if all required AllocationSequence objects
268 // are created.
269 if (!allocation_sequences_created_) {
270 return false;
271 }
272
273 // Check that all port allocation sequences are complete (not running).
274 if (std::any_of(sequences_.begin(), sequences_.end(),
275 [](const AllocationSequence* sequence) {
276 return sequence->state() == AllocationSequence::kRunning;
277 })) {
278 return false;
279 }
280
281 // If all allocated ports are in complete state, session must have got all
282 // expected candidates. Session will trigger candidates allocation complete
283 // signal.
284 if (!std::all_of(ports_.begin(), ports_.end(), [](const PortData& port) {
285 return (port.complete() || port.error());
286 })) {
287 return false;
288 }
289
290 return true;
291}
292
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000293void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
294 switch (message->message_id) {
295 case MSG_CONFIG_START:
296 ASSERT(rtc::Thread::Current() == network_thread_);
297 GetPortConfigurations();
298 break;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000299 case MSG_CONFIG_READY:
300 ASSERT(rtc::Thread::Current() == network_thread_);
301 OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
302 break;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000303 case MSG_ALLOCATE:
304 ASSERT(rtc::Thread::Current() == network_thread_);
305 OnAllocate();
306 break;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000307 case MSG_SEQUENCEOBJECTS_CREATED:
308 ASSERT(rtc::Thread::Current() == network_thread_);
309 OnAllocationSequenceObjectsCreated();
310 break;
311 case MSG_CONFIG_STOP:
312 ASSERT(rtc::Thread::Current() == network_thread_);
313 OnConfigStop();
314 break;
315 default:
316 ASSERT(false);
317 }
318}
319
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700320void BasicPortAllocatorSession::UpdateIceParametersInternal() {
321 for (PortData& port : ports_) {
322 port.port()->set_content_name(content_name());
323 port.port()->SetIceParameters(component(), ice_ufrag(), ice_pwd());
324 }
325}
326
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000327void BasicPortAllocatorSession::GetPortConfigurations() {
328 PortConfiguration* config = new PortConfiguration(allocator_->stun_servers(),
329 username(),
330 password());
331
deadbeef653b8e02015-11-11 12:55:10 -0800332 for (const RelayServerConfig& turn_server : allocator_->turn_servers()) {
333 config->AddRelay(turn_server);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000334 }
335 ConfigReady(config);
336}
337
338void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700339 network_thread_->Post(RTC_FROM_HERE, this, MSG_CONFIG_READY, config);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000340}
341
342// Adds a configuration to the list.
343void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
deadbeef653b8e02015-11-11 12:55:10 -0800344 if (config) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000345 configs_.push_back(config);
deadbeef653b8e02015-11-11 12:55:10 -0800346 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000347
348 AllocatePorts();
349}
350
351void BasicPortAllocatorSession::OnConfigStop() {
352 ASSERT(rtc::Thread::Current() == network_thread_);
353
354 // If any of the allocated ports have not completed the candidates allocation,
355 // mark those as error. Since session doesn't need any new candidates
356 // at this stage of the allocation, it's safe to discard any new candidates.
357 bool send_signal = false;
358 for (std::vector<PortData>::iterator it = ports_.begin();
359 it != ports_.end(); ++it) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700360 if (!it->complete() && !it->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000361 // Updating port state to error, which didn't finish allocating candidates
362 // yet.
363 it->set_error();
364 send_signal = true;
365 }
366 }
367
368 // Did we stop any running sequences?
369 for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
370 it != sequences_.end() && !send_signal; ++it) {
371 if ((*it)->state() == AllocationSequence::kStopped) {
372 send_signal = true;
373 }
374 }
375
376 // If we stopped anything that was running, send a done signal now.
377 if (send_signal) {
378 MaybeSignalCandidatesAllocationDone();
379 }
380}
381
382void BasicPortAllocatorSession::AllocatePorts() {
383 ASSERT(rtc::Thread::Current() == network_thread_);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700384 network_thread_->Post(RTC_FROM_HERE, this, MSG_ALLOCATE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000385}
386
387void BasicPortAllocatorSession::OnAllocate() {
388 if (network_manager_started_)
389 DoAllocate();
390
391 allocation_started_ = true;
392}
393
honghaiz8c404fa2015-09-28 07:59:43 -0700394void BasicPortAllocatorSession::GetNetworks(
395 std::vector<rtc::Network*>* networks) {
396 networks->clear();
397 rtc::NetworkManager* network_manager = allocator_->network_manager();
398 ASSERT(network_manager != nullptr);
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700399 // If the network permission state is BLOCKED, we just act as if the flag has
400 // been passed in.
honghaiz8c404fa2015-09-28 07:59:43 -0700401 if (network_manager->enumeration_permission() ==
guoweisea1012b2015-08-21 09:06:28 -0700402 rtc::NetworkManager::ENUMERATION_BLOCKED) {
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700403 set_flags(flags() | PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
404 }
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000405 // If the adapter enumeration is disabled, we'll just bind to any address
406 // instead of specific NIC. This is to ensure the same routing for http
407 // traffic by OS is also used here to avoid any local or public IP leakage
408 // during stun process.
409 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
honghaiz8c404fa2015-09-28 07:59:43 -0700410 network_manager->GetAnyAddressNetworks(networks);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000411 } else {
honghaiz8c404fa2015-09-28 07:59:43 -0700412 network_manager->GetNetworks(networks);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000413 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800414 networks->erase(std::remove_if(networks->begin(), networks->end(),
415 [this](rtc::Network* network) {
416 return allocator_->network_ignore_mask() &
417 network->type();
418 }),
419 networks->end());
honghaiz60347052016-05-31 18:29:12 -0700420
421 if (flags() & PORTALLOCATOR_DISABLE_COSTLY_NETWORKS) {
422 uint16_t lowest_cost = rtc::kNetworkCostMax;
423 for (rtc::Network* network : *networks) {
424 lowest_cost = std::min<uint16_t>(lowest_cost, network->GetCost());
425 }
426 networks->erase(std::remove_if(networks->begin(), networks->end(),
427 [lowest_cost](rtc::Network* network) {
428 return network->GetCost() >
429 lowest_cost + rtc::kNetworkCostLow;
430 }),
431 networks->end());
432 }
honghaiz8c404fa2015-09-28 07:59:43 -0700433}
434
435// For each network, see if we have a sequence that covers it already. If not,
436// create a new sequence to create the appropriate ports.
437void BasicPortAllocatorSession::DoAllocate() {
438 bool done_signal_needed = false;
439 std::vector<rtc::Network*> networks;
440 GetNetworks(&networks);
441
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000442 if (networks.empty()) {
443 LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
444 done_signal_needed = true;
445 } else {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200446 for (uint32_t i = 0; i < networks.size(); ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000447 PortConfiguration* config = NULL;
448 if (configs_.size() > 0)
449 config = configs_.back();
450
Peter Boström0c4e06b2015-10-07 12:23:21 +0200451 uint32_t sequence_flags = flags();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000452 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
453 // If all the ports are disabled we should just fire the allocation
454 // done event and return.
455 done_signal_needed = true;
456 break;
457 }
458
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000459 if (!config || config->relays.empty()) {
460 // No relay ports specified in this config.
461 sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
462 }
463
464 if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000465 networks[i]->GetBestIP().family() == AF_INET6) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000466 // Skip IPv6 networks unless the flag's been set.
467 continue;
468 }
469
470 // Disable phases that would only create ports equivalent to
471 // ones that we have already made.
472 DisableEquivalentPhases(networks[i], config, &sequence_flags);
473
474 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
475 // New AllocationSequence would have nothing to do, so don't make it.
476 continue;
477 }
478
479 AllocationSequence* sequence =
480 new AllocationSequence(this, networks[i], config, sequence_flags);
481 if (!sequence->Init()) {
482 delete sequence;
483 continue;
484 }
485 done_signal_needed = true;
486 sequence->SignalPortAllocationComplete.connect(
487 this, &BasicPortAllocatorSession::OnPortAllocationComplete);
488 if (running_)
489 sequence->Start();
490 sequences_.push_back(sequence);
491 }
492 }
493 if (done_signal_needed) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700494 network_thread_->Post(RTC_FROM_HERE, this, MSG_SEQUENCEOBJECTS_CREATED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000495 }
496}
497
498void BasicPortAllocatorSession::OnNetworksChanged() {
honghaiz8c404fa2015-09-28 07:59:43 -0700499 std::vector<rtc::Network*> networks;
500 GetNetworks(&networks);
501 for (AllocationSequence* sequence : sequences_) {
502 // Remove the network from the allocation sequence if it is not in
503 // |networks|.
504 if (!sequence->network_removed() &&
505 std::find(networks.begin(), networks.end(), sequence->network()) ==
506 networks.end()) {
507 sequence->OnNetworkRemoved();
508 }
509 }
510
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000511 network_manager_started_ = true;
512 if (allocation_started_)
513 DoAllocate();
514}
515
516void BasicPortAllocatorSession::DisableEquivalentPhases(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200517 rtc::Network* network,
518 PortConfiguration* config,
519 uint32_t* flags) {
520 for (uint32_t i = 0; i < sequences_.size() &&
521 (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES;
522 ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000523 sequences_[i]->DisableEquivalentPhases(network, config, flags);
524 }
525}
526
527void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
528 AllocationSequence * seq,
529 bool prepare_address) {
530 if (!port)
531 return;
532
533 LOG(LS_INFO) << "Adding allocated port for " << content_name();
534 port->set_content_name(content_name());
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700535 port->set_component(component());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000536 port->set_generation(generation());
537 if (allocator_->proxy().type != rtc::PROXY_NONE)
538 port->set_proxy(allocator_->user_agent(), allocator_->proxy());
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700539 port->set_send_retransmit_count_attribute(
540 (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000541
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000542 PortData data(port, seq);
543 ports_.push_back(data);
544
545 port->SignalCandidateReady.connect(
546 this, &BasicPortAllocatorSession::OnCandidateReady);
547 port->SignalPortComplete.connect(this,
548 &BasicPortAllocatorSession::OnPortComplete);
549 port->SignalDestroyed.connect(this,
550 &BasicPortAllocatorSession::OnPortDestroyed);
551 port->SignalPortError.connect(
552 this, &BasicPortAllocatorSession::OnPortError);
553 LOG_J(LS_INFO, port) << "Added port to allocator";
554
555 if (prepare_address)
556 port->PrepareAddress();
557}
558
559void BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
560 allocation_sequences_created_ = true;
561 // Send candidate allocation complete signal if we have no sequences.
562 MaybeSignalCandidatesAllocationDone();
563}
564
565void BasicPortAllocatorSession::OnCandidateReady(
566 Port* port, const Candidate& c) {
567 ASSERT(rtc::Thread::Current() == network_thread_);
568 PortData* data = FindPort(port);
569 ASSERT(data != NULL);
570 // Discarding any candidate signal if port allocation status is
571 // already in completed state.
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700572 if (data->complete() || data->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000573 return;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700574 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000575
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000576 ProtocolType pvalue;
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700577 bool candidate_protocol_enabled =
578 StringToProto(c.protocol().c_str(), &pvalue) &&
579 data->sequence()->ProtocolEnabled(pvalue);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000580
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700581 if (CheckCandidateFilter(c) && candidate_protocol_enabled) {
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700582 std::vector<Candidate> candidates;
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700583 candidates.push_back(SanitizeRelatedAddress(c));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000584 SignalCandidatesReady(this, candidates);
585 }
586
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700587 // Port has already been marked as having a pairable candidate.
588 // Nothing to do here.
589 if (data->has_pairable_candidate()) {
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700590 return;
591 }
592
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700593 // Mark that the port has a pairable candidate, either because we have a
594 // usable candidate from the port, or simply because the port is bound to the
595 // any address and therefore has no host candidate. This will trigger the port
596 // to start creating candidate pairs (connections) and issue connectivity
597 // checks.
598 if (CandidatePairable(c, port)) {
599 data->set_has_pairable_candidate(true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000600 SignalPortReady(this, port);
601 }
602}
603
604void BasicPortAllocatorSession::OnPortComplete(Port* port) {
605 ASSERT(rtc::Thread::Current() == network_thread_);
606 PortData* data = FindPort(port);
607 ASSERT(data != NULL);
608
609 // Ignore any late signals.
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700610 if (data->complete() || data->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000611 return;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700612 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000613
614 // Moving to COMPLETE state.
615 data->set_complete();
616 // Send candidate allocation complete signal if this was the last port.
617 MaybeSignalCandidatesAllocationDone();
618}
619
620void BasicPortAllocatorSession::OnPortError(Port* port) {
621 ASSERT(rtc::Thread::Current() == network_thread_);
622 PortData* data = FindPort(port);
623 ASSERT(data != NULL);
624 // We might have already given up on this port and stopped it.
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700625 if (data->complete() || data->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000626 return;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700627 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000628
629 // SignalAddressError is currently sent from StunPort/TurnPort.
630 // But this signal itself is generic.
631 data->set_error();
632 // Send candidate allocation complete signal if this was the last port.
633 MaybeSignalCandidatesAllocationDone();
634}
635
636void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
637 ProtocolType proto) {
638 std::vector<Candidate> candidates;
639 for (std::vector<PortData>::iterator it = ports_.begin();
640 it != ports_.end(); ++it) {
641 if (it->sequence() != seq)
642 continue;
643
644 const std::vector<Candidate>& potentials = it->port()->Candidates();
645 for (size_t i = 0; i < potentials.size(); ++i) {
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700646 if (!CheckCandidateFilter(potentials[i])) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000647 continue;
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700648 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000649 ProtocolType pvalue;
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700650 bool candidate_protocol_enabled =
651 StringToProto(potentials[i].protocol().c_str(), &pvalue) &&
652 pvalue == proto;
653 if (candidate_protocol_enabled) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000654 candidates.push_back(potentials[i]);
655 }
656 }
657 }
658
659 if (!candidates.empty()) {
660 SignalCandidatesReady(this, candidates);
661 }
662}
663
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700664bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const {
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700665 uint32_t filter = candidate_filter_;
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000666
667 // When binding to any address, before sending packets out, the getsockname
668 // returns all 0s, but after sending packets, it'll be the NIC used to
669 // send. All 0s is not a valid ICE candidate address and should be filtered
670 // out.
671 if (c.address().IsAnyIP()) {
672 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000673 }
674
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000675 if (c.type() == RELAY_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000676 return ((filter & CF_RELAY) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000677 } else if (c.type() == STUN_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000678 return ((filter & CF_REFLEXIVE) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000679 } else if (c.type() == LOCAL_PORT_TYPE) {
680 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
681 // We allow host candidates if the filter allows server-reflexive
682 // candidates and the candidate is a public IP. Because we don't generate
683 // server-reflexive candidates if they have the same IP as the host
684 // candidate (i.e. when the host candidate is a public IP), filtering to
685 // only server-reflexive candidates won't work right when the host
686 // candidates have public IPs.
687 return true;
688 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000689
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000690 return ((filter & CF_HOST) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000691 }
692 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000693}
694
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700695bool BasicPortAllocatorSession::CandidatePairable(const Candidate& c,
696 const Port* port) const {
697 bool candidate_signalable = CheckCandidateFilter(c);
698
699 // When device enumeration is disabled (to prevent non-default IP addresses
700 // from leaking), we ping from some local candidates even though we don't
701 // signal them. However, if host candidates are also disabled (for example, to
702 // prevent even default IP addresses from leaking), we still don't want to
703 // ping from them, even if device enumeration is disabled. Thus, we check for
704 // both device enumeration and host candidates being disabled.
705 bool network_enumeration_disabled = c.address().IsAnyIP();
706 bool can_ping_from_candidate =
707 (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
708 bool host_candidates_disabled = !(candidate_filter_ & CF_HOST);
709
710 return candidate_signalable ||
711 (network_enumeration_disabled && can_ping_from_candidate &&
712 !host_candidates_disabled);
713}
714
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000715void BasicPortAllocatorSession::OnPortAllocationComplete(
716 AllocationSequence* seq) {
717 // Send candidate allocation complete signal if all ports are done.
718 MaybeSignalCandidatesAllocationDone();
719}
720
721void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700722 if (CandidatesAllocationDone()) {
723 if (pooled()) {
724 LOG(LS_INFO) << "All candidates gathered for pooled session.";
725 } else {
726 LOG(LS_INFO) << "All candidates gathered for " << content_name() << ":"
727 << component() << ":" << generation();
728 }
729 SignalCandidatesAllocationDone(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000730 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000731}
732
733void BasicPortAllocatorSession::OnPortDestroyed(
734 PortInterface* port) {
735 ASSERT(rtc::Thread::Current() == network_thread_);
736 for (std::vector<PortData>::iterator iter = ports_.begin();
737 iter != ports_.end(); ++iter) {
738 if (port == iter->port()) {
739 ports_.erase(iter);
740 LOG_J(LS_INFO, port) << "Removed port from allocator ("
741 << static_cast<int>(ports_.size()) << " remaining)";
742 return;
743 }
744 }
745 ASSERT(false);
746}
747
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000748BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
749 Port* port) {
750 for (std::vector<PortData>::iterator it = ports_.begin();
751 it != ports_.end(); ++it) {
752 if (it->port() == port) {
753 return &*it;
754 }
755 }
756 return NULL;
757}
758
759// AllocationSequence
760
761AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
762 rtc::Network* network,
763 PortConfiguration* config,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200764 uint32_t flags)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000765 : session_(session),
766 network_(network),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000767 ip_(network->GetBestIP()),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000768 config_(config),
769 state_(kInit),
770 flags_(flags),
771 udp_socket_(),
772 udp_port_(NULL),
773 phase_(0) {
774}
775
776bool AllocationSequence::Init() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000777 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
778 udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
779 rtc::SocketAddress(ip_, 0), session_->allocator()->min_port(),
780 session_->allocator()->max_port()));
781 if (udp_socket_) {
782 udp_socket_->SignalReadPacket.connect(
783 this, &AllocationSequence::OnReadPacket);
784 }
785 // Continuing if |udp_socket_| is NULL, as local TCP and RelayPort using TCP
786 // are next available options to setup a communication channel.
787 }
788 return true;
789}
790
791void AllocationSequence::Clear() {
792 udp_port_ = NULL;
793 turn_ports_.clear();
794}
795
honghaiz8c404fa2015-09-28 07:59:43 -0700796void AllocationSequence::OnNetworkRemoved() {
797 // Stop the allocation sequence if its network is gone.
798 Stop();
799 network_removed_ = true;
800}
801
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000802AllocationSequence::~AllocationSequence() {
803 session_->network_thread()->Clear(this);
804}
805
806void AllocationSequence::DisableEquivalentPhases(rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200807 PortConfiguration* config, uint32_t* flags) {
honghaiz8c404fa2015-09-28 07:59:43 -0700808 if (network_removed_) {
809 // If the network of this allocation sequence has ever gone away,
810 // it won't be equivalent to the new network.
811 return;
812 }
813
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000814 if (!((network == network_) && (ip_ == network->GetBestIP()))) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000815 // Different network setup; nothing is equivalent.
816 return;
817 }
818
819 // Else turn off the stuff that we've already got covered.
820
821 // Every config implicitly specifies local, so turn that off right away.
822 *flags |= PORTALLOCATOR_DISABLE_UDP;
823 *flags |= PORTALLOCATOR_DISABLE_TCP;
824
825 if (config_ && config) {
826 if (config_->StunServers() == config->StunServers()) {
827 // Already got this STUN servers covered.
828 *flags |= PORTALLOCATOR_DISABLE_STUN;
829 }
830 if (!config_->relays.empty()) {
831 // Already got relays covered.
832 // NOTE: This will even skip a _different_ set of relay servers if we
833 // were to be given one, but that never happens in our codebase. Should
834 // probably get rid of the list in PortConfiguration and just keep a
835 // single relay server in each one.
836 *flags |= PORTALLOCATOR_DISABLE_RELAY;
837 }
838 }
839}
840
841void AllocationSequence::Start() {
842 state_ = kRunning;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700843 session_->network_thread()->Post(RTC_FROM_HERE, this, MSG_ALLOCATION_PHASE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000844}
845
846void AllocationSequence::Stop() {
847 // If the port is completed, don't set it to stopped.
848 if (state_ == kRunning) {
849 state_ = kStopped;
850 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
851 }
852}
853
854void AllocationSequence::OnMessage(rtc::Message* msg) {
855 ASSERT(rtc::Thread::Current() == session_->network_thread());
856 ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
857
858 const char* const PHASE_NAMES[kNumPhases] = {
859 "Udp", "Relay", "Tcp", "SslTcp"
860 };
861
862 // Perform all of the phases in the current step.
863 LOG_J(LS_INFO, network_) << "Allocation Phase="
864 << PHASE_NAMES[phase_];
865
866 switch (phase_) {
867 case PHASE_UDP:
868 CreateUDPPorts();
869 CreateStunPorts();
870 EnableProtocol(PROTO_UDP);
871 break;
872
873 case PHASE_RELAY:
874 CreateRelayPorts();
875 break;
876
877 case PHASE_TCP:
878 CreateTCPPorts();
879 EnableProtocol(PROTO_TCP);
880 break;
881
882 case PHASE_SSLTCP:
883 state_ = kCompleted;
884 EnableProtocol(PROTO_SSLTCP);
885 break;
886
887 default:
888 ASSERT(false);
889 }
890
891 if (state() == kRunning) {
892 ++phase_;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700893 session_->network_thread()->PostDelayed(RTC_FROM_HERE,
894 session_->allocator()->step_delay(),
895 this, MSG_ALLOCATION_PHASE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000896 } else {
897 // If all phases in AllocationSequence are completed, no allocation
898 // steps needed further. Canceling pending signal.
899 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
900 SignalPortAllocationComplete(this);
901 }
902}
903
904void AllocationSequence::EnableProtocol(ProtocolType proto) {
905 if (!ProtocolEnabled(proto)) {
906 protocols_.push_back(proto);
907 session_->OnProtocolEnabled(this, proto);
908 }
909}
910
911bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
912 for (ProtocolList::const_iterator it = protocols_.begin();
913 it != protocols_.end(); ++it) {
914 if (*it == proto)
915 return true;
916 }
917 return false;
918}
919
920void AllocationSequence::CreateUDPPorts() {
921 if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
922 LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
923 return;
924 }
925
926 // TODO(mallinath) - Remove UDPPort creating socket after shared socket
927 // is enabled completely.
928 UDPPort* port = NULL;
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800929 bool emit_local_candidate_for_anyaddress =
930 !IsFlagSet(PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000931 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700932 port = UDPPort::Create(
933 session_->network_thread(), session_->socket_factory(), network_,
934 udp_socket_.get(), session_->username(), session_->password(),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800935 session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000936 } else {
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700937 port = UDPPort::Create(
938 session_->network_thread(), session_->socket_factory(), network_, ip_,
939 session_->allocator()->min_port(), session_->allocator()->max_port(),
940 session_->username(), session_->password(),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800941 session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000942 }
943
944 if (port) {
945 // If shared socket is enabled, STUN candidate will be allocated by the
946 // UDPPort.
947 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
948 udp_port_ = port;
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +0000949 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000950
951 // If STUN is not disabled, setting stun server address to port.
952 if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000953 if (config_ && !config_->StunServers().empty()) {
954 LOG(LS_INFO) << "AllocationSequence: UDPPort will be handling the "
955 << "STUN candidate generation.";
956 port->set_server_addresses(config_->StunServers());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000957 }
958 }
959 }
960
961 session_->AddAllocatedPort(port, this, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000962 }
963}
964
965void AllocationSequence::CreateTCPPorts() {
966 if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
967 LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
968 return;
969 }
970
971 Port* port = TCPPort::Create(session_->network_thread(),
972 session_->socket_factory(),
973 network_, ip_,
974 session_->allocator()->min_port(),
975 session_->allocator()->max_port(),
976 session_->username(), session_->password(),
977 session_->allocator()->allow_tcp_listen());
978 if (port) {
979 session_->AddAllocatedPort(port, this, true);
980 // Since TCPPort is not created using shared socket, |port| will not be
981 // added to the dequeue.
982 }
983}
984
985void AllocationSequence::CreateStunPorts() {
986 if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
987 LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
988 return;
989 }
990
991 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
992 return;
993 }
994
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000995 if (!(config_ && !config_->StunServers().empty())) {
996 LOG(LS_WARNING)
997 << "AllocationSequence: No STUN server configured, skipping.";
998 return;
999 }
1000
1001 StunPort* port = StunPort::Create(session_->network_thread(),
1002 session_->socket_factory(),
1003 network_, ip_,
1004 session_->allocator()->min_port(),
1005 session_->allocator()->max_port(),
1006 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001007 config_->StunServers(),
1008 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001009 if (port) {
1010 session_->AddAllocatedPort(port, this, true);
1011 // Since StunPort is not created using shared socket, |port| will not be
1012 // added to the dequeue.
1013 }
1014}
1015
1016void AllocationSequence::CreateRelayPorts() {
1017 if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
1018 LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
1019 return;
1020 }
1021
1022 // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
1023 // ought to have a relay list for them here.
1024 ASSERT(config_ && !config_->relays.empty());
1025 if (!(config_ && !config_->relays.empty())) {
1026 LOG(LS_WARNING)
1027 << "AllocationSequence: No relay server configured, skipping.";
1028 return;
1029 }
1030
1031 PortConfiguration::RelayList::const_iterator relay;
1032 for (relay = config_->relays.begin();
1033 relay != config_->relays.end(); ++relay) {
1034 if (relay->type == RELAY_GTURN) {
1035 CreateGturnPort(*relay);
1036 } else if (relay->type == RELAY_TURN) {
1037 CreateTurnPort(*relay);
1038 } else {
1039 ASSERT(false);
1040 }
1041 }
1042}
1043
1044void AllocationSequence::CreateGturnPort(const RelayServerConfig& config) {
1045 // TODO(mallinath) - Rename RelayPort to GTurnPort.
1046 RelayPort* port = RelayPort::Create(session_->network_thread(),
1047 session_->socket_factory(),
1048 network_, ip_,
1049 session_->allocator()->min_port(),
1050 session_->allocator()->max_port(),
1051 config_->username, config_->password);
1052 if (port) {
1053 // Since RelayPort is not created using shared socket, |port| will not be
1054 // added to the dequeue.
1055 // Note: We must add the allocated port before we add addresses because
1056 // the latter will create candidates that need name and preference
1057 // settings. However, we also can't prepare the address (normally
1058 // done by AddAllocatedPort) until we have these addresses. So we
1059 // wait to do that until below.
1060 session_->AddAllocatedPort(port, this, false);
1061
1062 // Add the addresses of this protocol.
1063 PortList::const_iterator relay_port;
1064 for (relay_port = config.ports.begin();
1065 relay_port != config.ports.end();
1066 ++relay_port) {
1067 port->AddServerAddress(*relay_port);
1068 port->AddExternalAddress(*relay_port);
1069 }
1070 // Start fetching an address for this port.
1071 port->PrepareAddress();
1072 }
1073}
1074
1075void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
1076 PortList::const_iterator relay_port;
1077 for (relay_port = config.ports.begin();
1078 relay_port != config.ports.end(); ++relay_port) {
1079 TurnPort* port = NULL;
Guo-wei Shieh13d35f62015-08-26 15:32:56 -07001080
1081 // Skip UDP connections to relay servers if it's disallowed.
1082 if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP_RELAY) &&
1083 relay_port->proto == PROTO_UDP) {
1084 continue;
1085 }
1086
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001087 // Shared socket mode must be enabled only for UDP based ports. Hence
1088 // don't pass shared socket for ports which will create TCP sockets.
1089 // TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
1090 // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
1091 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
honghaizf421bdc2015-07-17 16:21:55 -07001092 relay_port->proto == PROTO_UDP && udp_socket_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001093 port = TurnPort::Create(session_->network_thread(),
1094 session_->socket_factory(),
1095 network_, udp_socket_.get(),
1096 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001097 *relay_port, config.credentials, config.priority,
1098 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001099 turn_ports_.push_back(port);
1100 // Listen to the port destroyed signal, to allow AllocationSequence to
1101 // remove entrt from it's map.
1102 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
1103 } else {
1104 port = TurnPort::Create(session_->network_thread(),
1105 session_->socket_factory(),
1106 network_, ip_,
1107 session_->allocator()->min_port(),
1108 session_->allocator()->max_port(),
1109 session_->username(),
1110 session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001111 *relay_port, config.credentials, config.priority,
1112 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001113 }
1114 ASSERT(port != NULL);
1115 session_->AddAllocatedPort(port, this, true);
1116 }
1117}
1118
1119void AllocationSequence::OnReadPacket(
1120 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
1121 const rtc::SocketAddress& remote_addr,
1122 const rtc::PacketTime& packet_time) {
1123 ASSERT(socket == udp_socket_.get());
1124
1125 bool turn_port_found = false;
1126
1127 // Try to find the TurnPort that matches the remote address. Note that the
1128 // message could be a STUN binding response if the TURN server is also used as
1129 // a STUN server. We don't want to parse every message here to check if it is
1130 // a STUN binding response, so we pass the message to TurnPort regardless of
1131 // the message type. The TurnPort will just ignore the message since it will
1132 // not find any request by transaction ID.
Sergey Ulanov17fa6722016-05-10 10:20:47 -07001133 for (TurnPort* port : turn_ports_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001134 if (port->server_address().address == remote_addr) {
Sergey Ulanov17fa6722016-05-10 10:20:47 -07001135 if (port->HandleIncomingPacket(socket, data, size, remote_addr,
1136 packet_time)) {
1137 return;
1138 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001139 turn_port_found = true;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001140 }
1141 }
1142
1143 if (udp_port_) {
1144 const ServerAddresses& stun_servers = udp_port_->server_addresses();
1145
1146 // Pass the packet to the UdpPort if there is no matching TurnPort, or if
1147 // the TURN server is also a STUN server.
1148 if (!turn_port_found ||
1149 stun_servers.find(remote_addr) != stun_servers.end()) {
Sergey Ulanov17fa6722016-05-10 10:20:47 -07001150 RTC_DCHECK(udp_port_->SharedSocket());
1151 udp_port_->HandleIncomingPacket(socket, data, size, remote_addr,
1152 packet_time);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001153 }
1154 }
1155}
1156
1157void AllocationSequence::OnPortDestroyed(PortInterface* port) {
1158 if (udp_port_ == port) {
1159 udp_port_ = NULL;
1160 return;
1161 }
1162
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +00001163 auto it = std::find(turn_ports_.begin(), turn_ports_.end(), port);
1164 if (it != turn_ports_.end()) {
1165 turn_ports_.erase(it);
1166 } else {
1167 LOG(LS_ERROR) << "Unexpected OnPortDestroyed for nonexistent port.";
1168 ASSERT(false);
1169 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001170}
1171
1172// PortConfiguration
1173PortConfiguration::PortConfiguration(
1174 const rtc::SocketAddress& stun_address,
1175 const std::string& username,
1176 const std::string& password)
1177 : stun_address(stun_address), username(username), password(password) {
1178 if (!stun_address.IsNil())
1179 stun_servers.insert(stun_address);
1180}
1181
1182PortConfiguration::PortConfiguration(const ServerAddresses& stun_servers,
1183 const std::string& username,
1184 const std::string& password)
1185 : stun_servers(stun_servers),
1186 username(username),
1187 password(password) {
1188 if (!stun_servers.empty())
1189 stun_address = *(stun_servers.begin());
1190}
1191
1192ServerAddresses PortConfiguration::StunServers() {
1193 if (!stun_address.IsNil() &&
1194 stun_servers.find(stun_address) == stun_servers.end()) {
1195 stun_servers.insert(stun_address);
1196 }
deadbeefc5d0d952015-07-16 10:22:21 -07001197 // Every UDP TURN server should also be used as a STUN server.
1198 ServerAddresses turn_servers = GetRelayServerAddresses(RELAY_TURN, PROTO_UDP);
1199 for (const rtc::SocketAddress& turn_server : turn_servers) {
1200 if (stun_servers.find(turn_server) == stun_servers.end()) {
1201 stun_servers.insert(turn_server);
1202 }
1203 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001204 return stun_servers;
1205}
1206
1207void PortConfiguration::AddRelay(const RelayServerConfig& config) {
1208 relays.push_back(config);
1209}
1210
1211bool PortConfiguration::SupportsProtocol(
1212 const RelayServerConfig& relay, ProtocolType type) const {
1213 PortList::const_iterator relay_port;
1214 for (relay_port = relay.ports.begin();
1215 relay_port != relay.ports.end();
1216 ++relay_port) {
1217 if (relay_port->proto == type)
1218 return true;
1219 }
1220 return false;
1221}
1222
1223bool PortConfiguration::SupportsProtocol(RelayType turn_type,
1224 ProtocolType type) const {
1225 for (size_t i = 0; i < relays.size(); ++i) {
1226 if (relays[i].type == turn_type &&
1227 SupportsProtocol(relays[i], type))
1228 return true;
1229 }
1230 return false;
1231}
1232
1233ServerAddresses PortConfiguration::GetRelayServerAddresses(
1234 RelayType turn_type, ProtocolType type) const {
1235 ServerAddresses servers;
1236 for (size_t i = 0; i < relays.size(); ++i) {
1237 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1238 servers.insert(relays[i].ports.front().address);
1239 }
1240 }
1241 return servers;
1242}
1243
1244} // namespace cricket