blob: bf61bc88fc9612074b6eaa5e387b026645027eb2 [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
170void BasicPortAllocatorSession::StartGettingPorts() {
171 network_thread_ = rtc::Thread::Current();
172 if (!socket_factory_) {
173 owned_socket_factory_.reset(
174 new rtc::BasicPacketSocketFactory(network_thread_));
175 socket_factory_ = owned_socket_factory_.get();
176 }
177
178 running_ = true;
179 network_thread_->Post(this, MSG_CONFIG_START);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000180}
181
182void BasicPortAllocatorSession::StopGettingPorts() {
183 ASSERT(rtc::Thread::Current() == network_thread_);
184 running_ = false;
honghaiz98db68f2015-09-29 07:58:17 -0700185 network_thread_->Post(this, MSG_CONFIG_STOP);
186 ClearGettingPorts();
187}
188
189void BasicPortAllocatorSession::ClearGettingPorts() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000190 network_thread_->Clear(this, MSG_ALLOCATE);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200191 for (uint32_t i = 0; i < sequences_.size(); ++i)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000192 sequences_[i]->Stop();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000193}
194
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700195std::vector<PortInterface*> BasicPortAllocatorSession::ReadyPorts() const {
196 std::vector<PortInterface*> ret;
197 for (const PortData& port : ports_) {
198 if (port.ready() || port.complete()) {
199 ret.push_back(port.port());
200 }
201 }
202 return ret;
203}
204
205std::vector<Candidate> BasicPortAllocatorSession::ReadyCandidates() const {
206 std::vector<Candidate> candidates;
207 for (const PortData& data : ports_) {
208 for (const Candidate& candidate : data.port()->Candidates()) {
209 if (!CheckCandidateFilter(candidate)) {
210 continue;
211 }
212 ProtocolType pvalue;
213 if (!StringToProto(candidate.protocol().c_str(), &pvalue) ||
214 !data.sequence()->ProtocolEnabled(pvalue)) {
215 continue;
216 }
217 candidates.push_back(candidate);
218 }
219 }
220 return candidates;
221}
222
223bool BasicPortAllocatorSession::CandidatesAllocationDone() const {
224 // Done only if all required AllocationSequence objects
225 // are created.
226 if (!allocation_sequences_created_) {
227 return false;
228 }
229
230 // Check that all port allocation sequences are complete (not running).
231 if (std::any_of(sequences_.begin(), sequences_.end(),
232 [](const AllocationSequence* sequence) {
233 return sequence->state() == AllocationSequence::kRunning;
234 })) {
235 return false;
236 }
237
238 // If all allocated ports are in complete state, session must have got all
239 // expected candidates. Session will trigger candidates allocation complete
240 // signal.
241 if (!std::all_of(ports_.begin(), ports_.end(), [](const PortData& port) {
242 return (port.complete() || port.error());
243 })) {
244 return false;
245 }
246
247 return true;
248}
249
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000250void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
251 switch (message->message_id) {
252 case MSG_CONFIG_START:
253 ASSERT(rtc::Thread::Current() == network_thread_);
254 GetPortConfigurations();
255 break;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000256 case MSG_CONFIG_READY:
257 ASSERT(rtc::Thread::Current() == network_thread_);
258 OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
259 break;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000260 case MSG_ALLOCATE:
261 ASSERT(rtc::Thread::Current() == network_thread_);
262 OnAllocate();
263 break;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000264 case MSG_SEQUENCEOBJECTS_CREATED:
265 ASSERT(rtc::Thread::Current() == network_thread_);
266 OnAllocationSequenceObjectsCreated();
267 break;
268 case MSG_CONFIG_STOP:
269 ASSERT(rtc::Thread::Current() == network_thread_);
270 OnConfigStop();
271 break;
272 default:
273 ASSERT(false);
274 }
275}
276
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700277void BasicPortAllocatorSession::UpdateIceParametersInternal() {
278 for (PortData& port : ports_) {
279 port.port()->set_content_name(content_name());
280 port.port()->SetIceParameters(component(), ice_ufrag(), ice_pwd());
281 }
282}
283
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000284void BasicPortAllocatorSession::GetPortConfigurations() {
285 PortConfiguration* config = new PortConfiguration(allocator_->stun_servers(),
286 username(),
287 password());
288
deadbeef653b8e02015-11-11 12:55:10 -0800289 for (const RelayServerConfig& turn_server : allocator_->turn_servers()) {
290 config->AddRelay(turn_server);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000291 }
292 ConfigReady(config);
293}
294
295void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
296 network_thread_->Post(this, MSG_CONFIG_READY, config);
297}
298
299// Adds a configuration to the list.
300void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
deadbeef653b8e02015-11-11 12:55:10 -0800301 if (config) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000302 configs_.push_back(config);
deadbeef653b8e02015-11-11 12:55:10 -0800303 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000304
305 AllocatePorts();
306}
307
308void BasicPortAllocatorSession::OnConfigStop() {
309 ASSERT(rtc::Thread::Current() == network_thread_);
310
311 // If any of the allocated ports have not completed the candidates allocation,
312 // mark those as error. Since session doesn't need any new candidates
313 // at this stage of the allocation, it's safe to discard any new candidates.
314 bool send_signal = false;
315 for (std::vector<PortData>::iterator it = ports_.begin();
316 it != ports_.end(); ++it) {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700317 if (!it->complete() && !it->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000318 // Updating port state to error, which didn't finish allocating candidates
319 // yet.
320 it->set_error();
321 send_signal = true;
322 }
323 }
324
325 // Did we stop any running sequences?
326 for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
327 it != sequences_.end() && !send_signal; ++it) {
328 if ((*it)->state() == AllocationSequence::kStopped) {
329 send_signal = true;
330 }
331 }
332
333 // If we stopped anything that was running, send a done signal now.
334 if (send_signal) {
335 MaybeSignalCandidatesAllocationDone();
336 }
337}
338
339void BasicPortAllocatorSession::AllocatePorts() {
340 ASSERT(rtc::Thread::Current() == network_thread_);
341 network_thread_->Post(this, MSG_ALLOCATE);
342}
343
344void BasicPortAllocatorSession::OnAllocate() {
345 if (network_manager_started_)
346 DoAllocate();
347
348 allocation_started_ = true;
349}
350
honghaiz8c404fa2015-09-28 07:59:43 -0700351void BasicPortAllocatorSession::GetNetworks(
352 std::vector<rtc::Network*>* networks) {
353 networks->clear();
354 rtc::NetworkManager* network_manager = allocator_->network_manager();
355 ASSERT(network_manager != nullptr);
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700356 // If the network permission state is BLOCKED, we just act as if the flag has
357 // been passed in.
honghaiz8c404fa2015-09-28 07:59:43 -0700358 if (network_manager->enumeration_permission() ==
guoweisea1012b2015-08-21 09:06:28 -0700359 rtc::NetworkManager::ENUMERATION_BLOCKED) {
Guo-wei Shieh47872ec2015-08-19 10:32:46 -0700360 set_flags(flags() | PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
361 }
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000362 // If the adapter enumeration is disabled, we'll just bind to any address
363 // instead of specific NIC. This is to ensure the same routing for http
364 // traffic by OS is also used here to avoid any local or public IP leakage
365 // during stun process.
366 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
honghaiz8c404fa2015-09-28 07:59:43 -0700367 network_manager->GetAnyAddressNetworks(networks);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000368 } else {
honghaiz8c404fa2015-09-28 07:59:43 -0700369 network_manager->GetNetworks(networks);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000370 }
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800371 networks->erase(std::remove_if(networks->begin(), networks->end(),
372 [this](rtc::Network* network) {
373 return allocator_->network_ignore_mask() &
374 network->type();
375 }),
376 networks->end());
honghaiz8c404fa2015-09-28 07:59:43 -0700377}
378
379// For each network, see if we have a sequence that covers it already. If not,
380// create a new sequence to create the appropriate ports.
381void BasicPortAllocatorSession::DoAllocate() {
382 bool done_signal_needed = false;
383 std::vector<rtc::Network*> networks;
384 GetNetworks(&networks);
385
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000386 if (networks.empty()) {
387 LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
388 done_signal_needed = true;
389 } else {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200390 for (uint32_t i = 0; i < networks.size(); ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000391 PortConfiguration* config = NULL;
392 if (configs_.size() > 0)
393 config = configs_.back();
394
Peter Boström0c4e06b2015-10-07 12:23:21 +0200395 uint32_t sequence_flags = flags();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000396 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
397 // If all the ports are disabled we should just fire the allocation
398 // done event and return.
399 done_signal_needed = true;
400 break;
401 }
402
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000403 if (!config || config->relays.empty()) {
404 // No relay ports specified in this config.
405 sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
406 }
407
408 if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000409 networks[i]->GetBestIP().family() == AF_INET6) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000410 // Skip IPv6 networks unless the flag's been set.
411 continue;
412 }
413
414 // Disable phases that would only create ports equivalent to
415 // ones that we have already made.
416 DisableEquivalentPhases(networks[i], config, &sequence_flags);
417
418 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
419 // New AllocationSequence would have nothing to do, so don't make it.
420 continue;
421 }
422
423 AllocationSequence* sequence =
424 new AllocationSequence(this, networks[i], config, sequence_flags);
425 if (!sequence->Init()) {
426 delete sequence;
427 continue;
428 }
429 done_signal_needed = true;
430 sequence->SignalPortAllocationComplete.connect(
431 this, &BasicPortAllocatorSession::OnPortAllocationComplete);
432 if (running_)
433 sequence->Start();
434 sequences_.push_back(sequence);
435 }
436 }
437 if (done_signal_needed) {
438 network_thread_->Post(this, MSG_SEQUENCEOBJECTS_CREATED);
439 }
440}
441
442void BasicPortAllocatorSession::OnNetworksChanged() {
honghaiz8c404fa2015-09-28 07:59:43 -0700443 std::vector<rtc::Network*> networks;
444 GetNetworks(&networks);
445 for (AllocationSequence* sequence : sequences_) {
446 // Remove the network from the allocation sequence if it is not in
447 // |networks|.
448 if (!sequence->network_removed() &&
449 std::find(networks.begin(), networks.end(), sequence->network()) ==
450 networks.end()) {
451 sequence->OnNetworkRemoved();
452 }
453 }
454
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000455 network_manager_started_ = true;
456 if (allocation_started_)
457 DoAllocate();
458}
459
460void BasicPortAllocatorSession::DisableEquivalentPhases(
Peter Boström0c4e06b2015-10-07 12:23:21 +0200461 rtc::Network* network,
462 PortConfiguration* config,
463 uint32_t* flags) {
464 for (uint32_t i = 0; i < sequences_.size() &&
465 (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES;
466 ++i) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000467 sequences_[i]->DisableEquivalentPhases(network, config, flags);
468 }
469}
470
471void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
472 AllocationSequence * seq,
473 bool prepare_address) {
474 if (!port)
475 return;
476
477 LOG(LS_INFO) << "Adding allocated port for " << content_name();
478 port->set_content_name(content_name());
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700479 port->set_component(component());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000480 port->set_generation(generation());
481 if (allocator_->proxy().type != rtc::PROXY_NONE)
482 port->set_proxy(allocator_->user_agent(), allocator_->proxy());
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700483 port->set_send_retransmit_count_attribute(
484 (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000485
486 // Push down the candidate_filter to individual port.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200487 uint32_t candidate_filter = allocator_->candidate_filter();
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000488
489 // When adapter enumeration is disabled, disable CF_HOST at port level so
490 // local address is not leaked by stunport in the candidate's related address.
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800491 if ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
492 (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) {
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000493 candidate_filter &= ~CF_HOST;
494 }
495 port->set_candidate_filter(candidate_filter);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000496
497 PortData data(port, seq);
498 ports_.push_back(data);
499
500 port->SignalCandidateReady.connect(
501 this, &BasicPortAllocatorSession::OnCandidateReady);
502 port->SignalPortComplete.connect(this,
503 &BasicPortAllocatorSession::OnPortComplete);
504 port->SignalDestroyed.connect(this,
505 &BasicPortAllocatorSession::OnPortDestroyed);
506 port->SignalPortError.connect(
507 this, &BasicPortAllocatorSession::OnPortError);
508 LOG_J(LS_INFO, port) << "Added port to allocator";
509
510 if (prepare_address)
511 port->PrepareAddress();
512}
513
514void BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
515 allocation_sequences_created_ = true;
516 // Send candidate allocation complete signal if we have no sequences.
517 MaybeSignalCandidatesAllocationDone();
518}
519
520void BasicPortAllocatorSession::OnCandidateReady(
521 Port* port, const Candidate& c) {
522 ASSERT(rtc::Thread::Current() == network_thread_);
523 PortData* data = FindPort(port);
524 ASSERT(data != NULL);
525 // Discarding any candidate signal if port allocation status is
526 // already in completed state.
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700527 if (data->complete() || data->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000528 return;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700529 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000530
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000531 ProtocolType pvalue;
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700532 bool candidate_signalable = CheckCandidateFilter(c);
Guo-wei Shieh898d21c2015-09-30 10:54:55 -0700533
534 // When device enumeration is disabled (to prevent non-default IP addresses
535 // from leaking), we ping from some local candidates even though we don't
536 // signal them. However, if host candidates are also disabled (for example, to
537 // prevent even default IP addresses from leaking), we still don't want to
538 // ping from them, even if device enumeration is disabled. Thus, we check for
539 // both device enumeration and host candidates being disabled.
540 bool network_enumeration_disabled = c.address().IsAnyIP();
541 bool can_ping_from_candidate =
542 (port->SharedSocket() || c.protocol() == TCP_PROTOCOL_NAME);
543 bool host_canidates_disabled = !(allocator_->candidate_filter() & CF_HOST);
544
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700545 bool candidate_pairable =
546 candidate_signalable ||
Guo-wei Shieh898d21c2015-09-30 10:54:55 -0700547 (network_enumeration_disabled && can_ping_from_candidate &&
548 !host_canidates_disabled);
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700549 bool candidate_protocol_enabled =
550 StringToProto(c.protocol().c_str(), &pvalue) &&
551 data->sequence()->ProtocolEnabled(pvalue);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000552
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700553 if (candidate_signalable && candidate_protocol_enabled) {
554 std::vector<Candidate> candidates;
555 candidates.push_back(c);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000556 SignalCandidatesReady(this, candidates);
557 }
558
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700559 // Port has been made ready. Nothing to do here.
560 if (data->ready()) {
561 return;
562 }
563
564 // Move the port to the READY state, either because we have a usable candidate
565 // from the port, or simply because the port is bound to the any address and
566 // therefore has no host candidate. This will trigger the port to start
567 // creating candidate pairs (connections) and issue connectivity checks.
568 if (candidate_pairable) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000569 data->set_ready();
570 SignalPortReady(this, port);
571 }
572}
573
574void BasicPortAllocatorSession::OnPortComplete(Port* port) {
575 ASSERT(rtc::Thread::Current() == network_thread_);
576 PortData* data = FindPort(port);
577 ASSERT(data != NULL);
578
579 // Ignore any late signals.
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700580 if (data->complete() || data->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000581 return;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700582 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000583
584 // Moving to COMPLETE state.
585 data->set_complete();
586 // Send candidate allocation complete signal if this was the last port.
587 MaybeSignalCandidatesAllocationDone();
588}
589
590void BasicPortAllocatorSession::OnPortError(Port* port) {
591 ASSERT(rtc::Thread::Current() == network_thread_);
592 PortData* data = FindPort(port);
593 ASSERT(data != NULL);
594 // We might have already given up on this port and stopped it.
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700595 if (data->complete() || data->error()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000596 return;
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700597 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000598
599 // SignalAddressError is currently sent from StunPort/TurnPort.
600 // But this signal itself is generic.
601 data->set_error();
602 // Send candidate allocation complete signal if this was the last port.
603 MaybeSignalCandidatesAllocationDone();
604}
605
606void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
607 ProtocolType proto) {
608 std::vector<Candidate> candidates;
609 for (std::vector<PortData>::iterator it = ports_.begin();
610 it != ports_.end(); ++it) {
611 if (it->sequence() != seq)
612 continue;
613
614 const std::vector<Candidate>& potentials = it->port()->Candidates();
615 for (size_t i = 0; i < potentials.size(); ++i) {
616 if (!CheckCandidateFilter(potentials[i]))
617 continue;
618 ProtocolType pvalue;
Guo-wei Shieh38f88932015-08-13 22:24:02 -0700619 bool candidate_protocol_enabled =
620 StringToProto(potentials[i].protocol().c_str(), &pvalue) &&
621 pvalue == proto;
622 if (candidate_protocol_enabled) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000623 candidates.push_back(potentials[i]);
624 }
625 }
626 }
627
628 if (!candidates.empty()) {
629 SignalCandidatesReady(this, candidates);
630 }
631}
632
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700633bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const {
Peter Boström0c4e06b2015-10-07 12:23:21 +0200634 uint32_t filter = allocator_->candidate_filter();
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000635
636 // When binding to any address, before sending packets out, the getsockname
637 // returns all 0s, but after sending packets, it'll be the NIC used to
638 // send. All 0s is not a valid ICE candidate address and should be filtered
639 // out.
640 if (c.address().IsAnyIP()) {
641 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000642 }
643
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000644 if (c.type() == RELAY_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000645 return ((filter & CF_RELAY) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000646 } else if (c.type() == STUN_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000647 return ((filter & CF_REFLEXIVE) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000648 } else if (c.type() == LOCAL_PORT_TYPE) {
649 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
650 // We allow host candidates if the filter allows server-reflexive
651 // candidates and the candidate is a public IP. Because we don't generate
652 // server-reflexive candidates if they have the same IP as the host
653 // candidate (i.e. when the host candidate is a public IP), filtering to
654 // only server-reflexive candidates won't work right when the host
655 // candidates have public IPs.
656 return true;
657 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000658
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000659 return ((filter & CF_HOST) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000660 }
661 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000662}
663
664void BasicPortAllocatorSession::OnPortAllocationComplete(
665 AllocationSequence* seq) {
666 // Send candidate allocation complete signal if all ports are done.
667 MaybeSignalCandidatesAllocationDone();
668}
669
670void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700671 if (CandidatesAllocationDone()) {
672 if (pooled()) {
673 LOG(LS_INFO) << "All candidates gathered for pooled session.";
674 } else {
675 LOG(LS_INFO) << "All candidates gathered for " << content_name() << ":"
676 << component() << ":" << generation();
677 }
678 SignalCandidatesAllocationDone(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000679 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000680}
681
682void BasicPortAllocatorSession::OnPortDestroyed(
683 PortInterface* port) {
684 ASSERT(rtc::Thread::Current() == network_thread_);
685 for (std::vector<PortData>::iterator iter = ports_.begin();
686 iter != ports_.end(); ++iter) {
687 if (port == iter->port()) {
688 ports_.erase(iter);
689 LOG_J(LS_INFO, port) << "Removed port from allocator ("
690 << static_cast<int>(ports_.size()) << " remaining)";
691 return;
692 }
693 }
694 ASSERT(false);
695}
696
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000697BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
698 Port* port) {
699 for (std::vector<PortData>::iterator it = ports_.begin();
700 it != ports_.end(); ++it) {
701 if (it->port() == port) {
702 return &*it;
703 }
704 }
705 return NULL;
706}
707
708// AllocationSequence
709
710AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
711 rtc::Network* network,
712 PortConfiguration* config,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200713 uint32_t flags)
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000714 : session_(session),
715 network_(network),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000716 ip_(network->GetBestIP()),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000717 config_(config),
718 state_(kInit),
719 flags_(flags),
720 udp_socket_(),
721 udp_port_(NULL),
722 phase_(0) {
723}
724
725bool AllocationSequence::Init() {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000726 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
727 udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
728 rtc::SocketAddress(ip_, 0), session_->allocator()->min_port(),
729 session_->allocator()->max_port()));
730 if (udp_socket_) {
731 udp_socket_->SignalReadPacket.connect(
732 this, &AllocationSequence::OnReadPacket);
733 }
734 // Continuing if |udp_socket_| is NULL, as local TCP and RelayPort using TCP
735 // are next available options to setup a communication channel.
736 }
737 return true;
738}
739
740void AllocationSequence::Clear() {
741 udp_port_ = NULL;
742 turn_ports_.clear();
743}
744
honghaiz8c404fa2015-09-28 07:59:43 -0700745void AllocationSequence::OnNetworkRemoved() {
746 // Stop the allocation sequence if its network is gone.
747 Stop();
748 network_removed_ = true;
749}
750
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000751AllocationSequence::~AllocationSequence() {
752 session_->network_thread()->Clear(this);
753}
754
755void AllocationSequence::DisableEquivalentPhases(rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200756 PortConfiguration* config, uint32_t* flags) {
honghaiz8c404fa2015-09-28 07:59:43 -0700757 if (network_removed_) {
758 // If the network of this allocation sequence has ever gone away,
759 // it won't be equivalent to the new network.
760 return;
761 }
762
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000763 if (!((network == network_) && (ip_ == network->GetBestIP()))) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000764 // Different network setup; nothing is equivalent.
765 return;
766 }
767
768 // Else turn off the stuff that we've already got covered.
769
770 // Every config implicitly specifies local, so turn that off right away.
771 *flags |= PORTALLOCATOR_DISABLE_UDP;
772 *flags |= PORTALLOCATOR_DISABLE_TCP;
773
774 if (config_ && config) {
775 if (config_->StunServers() == config->StunServers()) {
776 // Already got this STUN servers covered.
777 *flags |= PORTALLOCATOR_DISABLE_STUN;
778 }
779 if (!config_->relays.empty()) {
780 // Already got relays covered.
781 // NOTE: This will even skip a _different_ set of relay servers if we
782 // were to be given one, but that never happens in our codebase. Should
783 // probably get rid of the list in PortConfiguration and just keep a
784 // single relay server in each one.
785 *flags |= PORTALLOCATOR_DISABLE_RELAY;
786 }
787 }
788}
789
790void AllocationSequence::Start() {
791 state_ = kRunning;
792 session_->network_thread()->Post(this, MSG_ALLOCATION_PHASE);
793}
794
795void AllocationSequence::Stop() {
796 // If the port is completed, don't set it to stopped.
797 if (state_ == kRunning) {
798 state_ = kStopped;
799 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
800 }
801}
802
803void AllocationSequence::OnMessage(rtc::Message* msg) {
804 ASSERT(rtc::Thread::Current() == session_->network_thread());
805 ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
806
807 const char* const PHASE_NAMES[kNumPhases] = {
808 "Udp", "Relay", "Tcp", "SslTcp"
809 };
810
811 // Perform all of the phases in the current step.
812 LOG_J(LS_INFO, network_) << "Allocation Phase="
813 << PHASE_NAMES[phase_];
814
815 switch (phase_) {
816 case PHASE_UDP:
817 CreateUDPPorts();
818 CreateStunPorts();
819 EnableProtocol(PROTO_UDP);
820 break;
821
822 case PHASE_RELAY:
823 CreateRelayPorts();
824 break;
825
826 case PHASE_TCP:
827 CreateTCPPorts();
828 EnableProtocol(PROTO_TCP);
829 break;
830
831 case PHASE_SSLTCP:
832 state_ = kCompleted;
833 EnableProtocol(PROTO_SSLTCP);
834 break;
835
836 default:
837 ASSERT(false);
838 }
839
840 if (state() == kRunning) {
841 ++phase_;
842 session_->network_thread()->PostDelayed(
843 session_->allocator()->step_delay(),
844 this, MSG_ALLOCATION_PHASE);
845 } else {
846 // If all phases in AllocationSequence are completed, no allocation
847 // steps needed further. Canceling pending signal.
848 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
849 SignalPortAllocationComplete(this);
850 }
851}
852
853void AllocationSequence::EnableProtocol(ProtocolType proto) {
854 if (!ProtocolEnabled(proto)) {
855 protocols_.push_back(proto);
856 session_->OnProtocolEnabled(this, proto);
857 }
858}
859
860bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
861 for (ProtocolList::const_iterator it = protocols_.begin();
862 it != protocols_.end(); ++it) {
863 if (*it == proto)
864 return true;
865 }
866 return false;
867}
868
869void AllocationSequence::CreateUDPPorts() {
870 if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
871 LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
872 return;
873 }
874
875 // TODO(mallinath) - Remove UDPPort creating socket after shared socket
876 // is enabled completely.
877 UDPPort* port = NULL;
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800878 bool emit_local_candidate_for_anyaddress =
879 !IsFlagSet(PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000880 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700881 port = UDPPort::Create(
882 session_->network_thread(), session_->socket_factory(), network_,
883 udp_socket_.get(), session_->username(), session_->password(),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800884 session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000885 } else {
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700886 port = UDPPort::Create(
887 session_->network_thread(), session_->socket_factory(), network_, ip_,
888 session_->allocator()->min_port(), session_->allocator()->max_port(),
889 session_->username(), session_->password(),
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800890 session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000891 }
892
893 if (port) {
894 // If shared socket is enabled, STUN candidate will be allocated by the
895 // UDPPort.
896 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
897 udp_port_ = port;
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +0000898 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000899
900 // If STUN is not disabled, setting stun server address to port.
901 if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000902 if (config_ && !config_->StunServers().empty()) {
903 LOG(LS_INFO) << "AllocationSequence: UDPPort will be handling the "
904 << "STUN candidate generation.";
905 port->set_server_addresses(config_->StunServers());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000906 }
907 }
908 }
909
910 session_->AddAllocatedPort(port, this, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000911 }
912}
913
914void AllocationSequence::CreateTCPPorts() {
915 if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
916 LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
917 return;
918 }
919
920 Port* port = TCPPort::Create(session_->network_thread(),
921 session_->socket_factory(),
922 network_, ip_,
923 session_->allocator()->min_port(),
924 session_->allocator()->max_port(),
925 session_->username(), session_->password(),
926 session_->allocator()->allow_tcp_listen());
927 if (port) {
928 session_->AddAllocatedPort(port, this, true);
929 // Since TCPPort is not created using shared socket, |port| will not be
930 // added to the dequeue.
931 }
932}
933
934void AllocationSequence::CreateStunPorts() {
935 if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
936 LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
937 return;
938 }
939
940 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
941 return;
942 }
943
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000944 if (!(config_ && !config_->StunServers().empty())) {
945 LOG(LS_WARNING)
946 << "AllocationSequence: No STUN server configured, skipping.";
947 return;
948 }
949
950 StunPort* port = StunPort::Create(session_->network_thread(),
951 session_->socket_factory(),
952 network_, ip_,
953 session_->allocator()->min_port(),
954 session_->allocator()->max_port(),
955 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000956 config_->StunServers(),
957 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000958 if (port) {
959 session_->AddAllocatedPort(port, this, true);
960 // Since StunPort is not created using shared socket, |port| will not be
961 // added to the dequeue.
962 }
963}
964
965void AllocationSequence::CreateRelayPorts() {
966 if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
967 LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
968 return;
969 }
970
971 // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
972 // ought to have a relay list for them here.
973 ASSERT(config_ && !config_->relays.empty());
974 if (!(config_ && !config_->relays.empty())) {
975 LOG(LS_WARNING)
976 << "AllocationSequence: No relay server configured, skipping.";
977 return;
978 }
979
980 PortConfiguration::RelayList::const_iterator relay;
981 for (relay = config_->relays.begin();
982 relay != config_->relays.end(); ++relay) {
983 if (relay->type == RELAY_GTURN) {
984 CreateGturnPort(*relay);
985 } else if (relay->type == RELAY_TURN) {
986 CreateTurnPort(*relay);
987 } else {
988 ASSERT(false);
989 }
990 }
991}
992
993void AllocationSequence::CreateGturnPort(const RelayServerConfig& config) {
994 // TODO(mallinath) - Rename RelayPort to GTurnPort.
995 RelayPort* port = RelayPort::Create(session_->network_thread(),
996 session_->socket_factory(),
997 network_, ip_,
998 session_->allocator()->min_port(),
999 session_->allocator()->max_port(),
1000 config_->username, config_->password);
1001 if (port) {
1002 // Since RelayPort is not created using shared socket, |port| will not be
1003 // added to the dequeue.
1004 // Note: We must add the allocated port before we add addresses because
1005 // the latter will create candidates that need name and preference
1006 // settings. However, we also can't prepare the address (normally
1007 // done by AddAllocatedPort) until we have these addresses. So we
1008 // wait to do that until below.
1009 session_->AddAllocatedPort(port, this, false);
1010
1011 // Add the addresses of this protocol.
1012 PortList::const_iterator relay_port;
1013 for (relay_port = config.ports.begin();
1014 relay_port != config.ports.end();
1015 ++relay_port) {
1016 port->AddServerAddress(*relay_port);
1017 port->AddExternalAddress(*relay_port);
1018 }
1019 // Start fetching an address for this port.
1020 port->PrepareAddress();
1021 }
1022}
1023
1024void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
1025 PortList::const_iterator relay_port;
1026 for (relay_port = config.ports.begin();
1027 relay_port != config.ports.end(); ++relay_port) {
1028 TurnPort* port = NULL;
Guo-wei Shieh13d35f62015-08-26 15:32:56 -07001029
1030 // Skip UDP connections to relay servers if it's disallowed.
1031 if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP_RELAY) &&
1032 relay_port->proto == PROTO_UDP) {
1033 continue;
1034 }
1035
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001036 // Shared socket mode must be enabled only for UDP based ports. Hence
1037 // don't pass shared socket for ports which will create TCP sockets.
1038 // TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
1039 // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
1040 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
honghaizf421bdc2015-07-17 16:21:55 -07001041 relay_port->proto == PROTO_UDP && udp_socket_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001042 port = TurnPort::Create(session_->network_thread(),
1043 session_->socket_factory(),
1044 network_, udp_socket_.get(),
1045 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001046 *relay_port, config.credentials, config.priority,
1047 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001048 turn_ports_.push_back(port);
1049 // Listen to the port destroyed signal, to allow AllocationSequence to
1050 // remove entrt from it's map.
1051 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
1052 } else {
1053 port = TurnPort::Create(session_->network_thread(),
1054 session_->socket_factory(),
1055 network_, ip_,
1056 session_->allocator()->min_port(),
1057 session_->allocator()->max_port(),
1058 session_->username(),
1059 session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001060 *relay_port, config.credentials, config.priority,
1061 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001062 }
1063 ASSERT(port != NULL);
1064 session_->AddAllocatedPort(port, this, true);
1065 }
1066}
1067
1068void AllocationSequence::OnReadPacket(
1069 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
1070 const rtc::SocketAddress& remote_addr,
1071 const rtc::PacketTime& packet_time) {
1072 ASSERT(socket == udp_socket_.get());
1073
1074 bool turn_port_found = false;
1075
1076 // Try to find the TurnPort that matches the remote address. Note that the
1077 // message could be a STUN binding response if the TURN server is also used as
1078 // a STUN server. We don't want to parse every message here to check if it is
1079 // a STUN binding response, so we pass the message to TurnPort regardless of
1080 // the message type. The TurnPort will just ignore the message since it will
1081 // not find any request by transaction ID.
Sergey Ulanov17fa6722016-05-10 10:20:47 -07001082 for (TurnPort* port : turn_ports_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001083 if (port->server_address().address == remote_addr) {
Sergey Ulanov17fa6722016-05-10 10:20:47 -07001084 if (port->HandleIncomingPacket(socket, data, size, remote_addr,
1085 packet_time)) {
1086 return;
1087 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001088 turn_port_found = true;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001089 }
1090 }
1091
1092 if (udp_port_) {
1093 const ServerAddresses& stun_servers = udp_port_->server_addresses();
1094
1095 // Pass the packet to the UdpPort if there is no matching TurnPort, or if
1096 // the TURN server is also a STUN server.
1097 if (!turn_port_found ||
1098 stun_servers.find(remote_addr) != stun_servers.end()) {
Sergey Ulanov17fa6722016-05-10 10:20:47 -07001099 RTC_DCHECK(udp_port_->SharedSocket());
1100 udp_port_->HandleIncomingPacket(socket, data, size, remote_addr,
1101 packet_time);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001102 }
1103 }
1104}
1105
1106void AllocationSequence::OnPortDestroyed(PortInterface* port) {
1107 if (udp_port_ == port) {
1108 udp_port_ = NULL;
1109 return;
1110 }
1111
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +00001112 auto it = std::find(turn_ports_.begin(), turn_ports_.end(), port);
1113 if (it != turn_ports_.end()) {
1114 turn_ports_.erase(it);
1115 } else {
1116 LOG(LS_ERROR) << "Unexpected OnPortDestroyed for nonexistent port.";
1117 ASSERT(false);
1118 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001119}
1120
1121// PortConfiguration
1122PortConfiguration::PortConfiguration(
1123 const rtc::SocketAddress& stun_address,
1124 const std::string& username,
1125 const std::string& password)
1126 : stun_address(stun_address), username(username), password(password) {
1127 if (!stun_address.IsNil())
1128 stun_servers.insert(stun_address);
1129}
1130
1131PortConfiguration::PortConfiguration(const ServerAddresses& stun_servers,
1132 const std::string& username,
1133 const std::string& password)
1134 : stun_servers(stun_servers),
1135 username(username),
1136 password(password) {
1137 if (!stun_servers.empty())
1138 stun_address = *(stun_servers.begin());
1139}
1140
1141ServerAddresses PortConfiguration::StunServers() {
1142 if (!stun_address.IsNil() &&
1143 stun_servers.find(stun_address) == stun_servers.end()) {
1144 stun_servers.insert(stun_address);
1145 }
deadbeefc5d0d952015-07-16 10:22:21 -07001146 // Every UDP TURN server should also be used as a STUN server.
1147 ServerAddresses turn_servers = GetRelayServerAddresses(RELAY_TURN, PROTO_UDP);
1148 for (const rtc::SocketAddress& turn_server : turn_servers) {
1149 if (stun_servers.find(turn_server) == stun_servers.end()) {
1150 stun_servers.insert(turn_server);
1151 }
1152 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001153 return stun_servers;
1154}
1155
1156void PortConfiguration::AddRelay(const RelayServerConfig& config) {
1157 relays.push_back(config);
1158}
1159
1160bool PortConfiguration::SupportsProtocol(
1161 const RelayServerConfig& relay, ProtocolType type) const {
1162 PortList::const_iterator relay_port;
1163 for (relay_port = relay.ports.begin();
1164 relay_port != relay.ports.end();
1165 ++relay_port) {
1166 if (relay_port->proto == type)
1167 return true;
1168 }
1169 return false;
1170}
1171
1172bool PortConfiguration::SupportsProtocol(RelayType turn_type,
1173 ProtocolType type) const {
1174 for (size_t i = 0; i < relays.size(); ++i) {
1175 if (relays[i].type == turn_type &&
1176 SupportsProtocol(relays[i], type))
1177 return true;
1178 }
1179 return false;
1180}
1181
1182ServerAddresses PortConfiguration::GetRelayServerAddresses(
1183 RelayType turn_type, ProtocolType type) const {
1184 ServerAddresses servers;
1185 for (size_t i = 0; i < relays.size(); ++i) {
1186 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1187 servers.insert(relays[i].ports.front().address);
1188 }
1189 }
1190 return servers;
1191}
1192
1193} // namespace cricket