blob: 5c322da59e458f540360852711ce8656134085cd [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
13#include <string>
14#include <vector>
15
16#include "webrtc/p2p/base/basicpacketsocketfactory.h"
17#include "webrtc/p2p/base/common.h"
18#include "webrtc/p2p/base/port.h"
19#include "webrtc/p2p/base/relayport.h"
20#include "webrtc/p2p/base/stunport.h"
21#include "webrtc/p2p/base/tcpport.h"
22#include "webrtc/p2p/base/turnport.h"
23#include "webrtc/p2p/base/udpport.h"
24#include "webrtc/base/common.h"
25#include "webrtc/base/helpers.h"
26#include "webrtc/base/logging.h"
27
28using rtc::CreateRandomId;
29using rtc::CreateRandomString;
30
31namespace {
32
33enum {
34 MSG_CONFIG_START,
35 MSG_CONFIG_READY,
36 MSG_ALLOCATE,
37 MSG_ALLOCATION_PHASE,
38 MSG_SHAKE,
39 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
50const int SHAKE_MIN_DELAY = 45 * 1000; // 45 seconds
51const int SHAKE_MAX_DELAY = 90 * 1000; // 90 seconds
52
53int ShakeDelay() {
54 int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1;
55 return SHAKE_MIN_DELAY + CreateRandomId() % range;
56}
57
58} // namespace
59
60namespace cricket {
61
62const uint32 DISABLE_ALL_PHASES =
63 PORTALLOCATOR_DISABLE_UDP
64 | PORTALLOCATOR_DISABLE_TCP
65 | PORTALLOCATOR_DISABLE_STUN
66 | PORTALLOCATOR_DISABLE_RELAY;
67
68// Performs the allocation of ports, in a sequenced (timed) manner, for a given
69// network and IP address.
70class AllocationSequence : public rtc::MessageHandler,
71 public sigslot::has_slots<> {
72 public:
73 enum State {
74 kInit, // Initial state.
75 kRunning, // Started allocating ports.
76 kStopped, // Stopped from running.
77 kCompleted, // All ports are allocated.
78
79 // kInit --> kRunning --> {kCompleted|kStopped}
80 };
81
82 AllocationSequence(BasicPortAllocatorSession* session,
83 rtc::Network* network,
84 PortConfiguration* config,
85 uint32 flags);
86 ~AllocationSequence();
87 bool Init();
88 void Clear();
89
90 State state() const { return state_; }
91
92 // Disables the phases for a new sequence that this one already covers for an
93 // equivalent network setup.
94 void DisableEquivalentPhases(rtc::Network* network,
95 PortConfiguration* config, uint32* flags);
96
97 // Starts and stops the sequence. When started, it will continue allocating
98 // new ports on its own timed schedule.
99 void Start();
100 void Stop();
101
102 // MessageHandler
103 void OnMessage(rtc::Message* msg);
104
105 void EnableProtocol(ProtocolType proto);
106 bool ProtocolEnabled(ProtocolType proto) const;
107
108 // Signal from AllocationSequence, when it's done with allocating ports.
109 // This signal is useful, when port allocation fails which doesn't result
110 // in any candidates. Using this signal BasicPortAllocatorSession can send
111 // its candidate discovery conclusion signal. Without this signal,
112 // BasicPortAllocatorSession doesn't have any event to trigger signal. This
113 // can also be achieved by starting timer in BPAS.
114 sigslot::signal1<AllocationSequence*> SignalPortAllocationComplete;
115
116 private:
117 typedef std::vector<ProtocolType> ProtocolList;
118
119 bool IsFlagSet(uint32 flag) {
120 return ((flags_ & flag) != 0);
121 }
122 void CreateUDPPorts();
123 void CreateTCPPorts();
124 void CreateStunPorts();
125 void CreateRelayPorts();
126 void CreateGturnPort(const RelayServerConfig& config);
127 void CreateTurnPort(const RelayServerConfig& config);
128
129 void OnReadPacket(rtc::AsyncPacketSocket* socket,
130 const char* data, size_t size,
131 const rtc::SocketAddress& remote_addr,
132 const rtc::PacketTime& packet_time);
133
134 void OnPortDestroyed(PortInterface* port);
135
136 BasicPortAllocatorSession* session_;
137 rtc::Network* network_;
138 rtc::IPAddress ip_;
139 PortConfiguration* config_;
140 State state_;
141 uint32 flags_;
142 ProtocolList protocols_;
143 rtc::scoped_ptr<rtc::AsyncPacketSocket> udp_socket_;
144 // There will be only one udp port per AllocationSequence.
145 UDPPort* udp_port_;
146 std::vector<TurnPort*> turn_ports_;
147 int phase_;
148};
149
150// BasicPortAllocator
151BasicPortAllocator::BasicPortAllocator(
152 rtc::NetworkManager* network_manager,
153 rtc::PacketSocketFactory* socket_factory)
154 : network_manager_(network_manager),
155 socket_factory_(socket_factory) {
156 ASSERT(socket_factory_ != NULL);
157 Construct();
158}
159
160BasicPortAllocator::BasicPortAllocator(
161 rtc::NetworkManager* network_manager)
162 : network_manager_(network_manager),
163 socket_factory_(NULL) {
164 Construct();
165}
166
167BasicPortAllocator::BasicPortAllocator(
168 rtc::NetworkManager* network_manager,
169 rtc::PacketSocketFactory* socket_factory,
170 const ServerAddresses& stun_servers)
171 : network_manager_(network_manager),
172 socket_factory_(socket_factory),
173 stun_servers_(stun_servers) {
174 ASSERT(socket_factory_ != NULL);
175 Construct();
176}
177
178BasicPortAllocator::BasicPortAllocator(
179 rtc::NetworkManager* network_manager,
180 const ServerAddresses& stun_servers,
181 const rtc::SocketAddress& relay_address_udp,
182 const rtc::SocketAddress& relay_address_tcp,
183 const rtc::SocketAddress& relay_address_ssl)
184 : network_manager_(network_manager),
185 socket_factory_(NULL),
186 stun_servers_(stun_servers) {
187
188 RelayServerConfig config(RELAY_GTURN);
189 if (!relay_address_udp.IsNil())
190 config.ports.push_back(ProtocolAddress(relay_address_udp, PROTO_UDP));
191 if (!relay_address_tcp.IsNil())
192 config.ports.push_back(ProtocolAddress(relay_address_tcp, PROTO_TCP));
193 if (!relay_address_ssl.IsNil())
194 config.ports.push_back(ProtocolAddress(relay_address_ssl, PROTO_SSLTCP));
195
196 if (!config.ports.empty())
197 AddRelay(config);
198
199 Construct();
200}
201
202void BasicPortAllocator::Construct() {
203 allow_tcp_listen_ = true;
204}
205
206BasicPortAllocator::~BasicPortAllocator() {
207}
208
209PortAllocatorSession *BasicPortAllocator::CreateSessionInternal(
210 const std::string& content_name, int component,
211 const std::string& ice_ufrag, const std::string& ice_pwd) {
212 return new BasicPortAllocatorSession(
213 this, content_name, component, ice_ufrag, ice_pwd);
214}
215
216
217// BasicPortAllocatorSession
218BasicPortAllocatorSession::BasicPortAllocatorSession(
219 BasicPortAllocator *allocator,
220 const std::string& content_name,
221 int component,
222 const std::string& ice_ufrag,
223 const std::string& ice_pwd)
224 : PortAllocatorSession(content_name, component,
225 ice_ufrag, ice_pwd, allocator->flags()),
226 allocator_(allocator), network_thread_(NULL),
227 socket_factory_(allocator->socket_factory()),
228 allocation_started_(false),
229 network_manager_started_(false),
230 running_(false),
231 allocation_sequences_created_(false) {
232 allocator_->network_manager()->SignalNetworksChanged.connect(
233 this, &BasicPortAllocatorSession::OnNetworksChanged);
234 allocator_->network_manager()->StartUpdating();
235}
236
237BasicPortAllocatorSession::~BasicPortAllocatorSession() {
238 allocator_->network_manager()->StopUpdating();
239 if (network_thread_ != NULL)
240 network_thread_->Clear(this);
241
242 for (uint32 i = 0; i < sequences_.size(); ++i) {
243 // AllocationSequence should clear it's map entry for turn ports before
244 // ports are destroyed.
245 sequences_[i]->Clear();
246 }
247
248 std::vector<PortData>::iterator it;
249 for (it = ports_.begin(); it != ports_.end(); it++)
250 delete it->port();
251
252 for (uint32 i = 0; i < configs_.size(); ++i)
253 delete configs_[i];
254
255 for (uint32 i = 0; i < sequences_.size(); ++i)
256 delete sequences_[i];
257}
258
259void BasicPortAllocatorSession::StartGettingPorts() {
260 network_thread_ = rtc::Thread::Current();
261 if (!socket_factory_) {
262 owned_socket_factory_.reset(
263 new rtc::BasicPacketSocketFactory(network_thread_));
264 socket_factory_ = owned_socket_factory_.get();
265 }
266
267 running_ = true;
268 network_thread_->Post(this, MSG_CONFIG_START);
269
270 if (flags() & PORTALLOCATOR_ENABLE_SHAKER)
271 network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
272}
273
274void BasicPortAllocatorSession::StopGettingPorts() {
275 ASSERT(rtc::Thread::Current() == network_thread_);
276 running_ = false;
277 network_thread_->Clear(this, MSG_ALLOCATE);
278 for (uint32 i = 0; i < sequences_.size(); ++i)
279 sequences_[i]->Stop();
280 network_thread_->Post(this, MSG_CONFIG_STOP);
281}
282
283void BasicPortAllocatorSession::OnMessage(rtc::Message *message) {
284 switch (message->message_id) {
285 case MSG_CONFIG_START:
286 ASSERT(rtc::Thread::Current() == network_thread_);
287 GetPortConfigurations();
288 break;
289
290 case MSG_CONFIG_READY:
291 ASSERT(rtc::Thread::Current() == network_thread_);
292 OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
293 break;
294
295 case MSG_ALLOCATE:
296 ASSERT(rtc::Thread::Current() == network_thread_);
297 OnAllocate();
298 break;
299
300 case MSG_SHAKE:
301 ASSERT(rtc::Thread::Current() == network_thread_);
302 OnShake();
303 break;
304 case MSG_SEQUENCEOBJECTS_CREATED:
305 ASSERT(rtc::Thread::Current() == network_thread_);
306 OnAllocationSequenceObjectsCreated();
307 break;
308 case MSG_CONFIG_STOP:
309 ASSERT(rtc::Thread::Current() == network_thread_);
310 OnConfigStop();
311 break;
312 default:
313 ASSERT(false);
314 }
315}
316
317void BasicPortAllocatorSession::GetPortConfigurations() {
318 PortConfiguration* config = new PortConfiguration(allocator_->stun_servers(),
319 username(),
320 password());
321
322 for (size_t i = 0; i < allocator_->relays().size(); ++i) {
323 config->AddRelay(allocator_->relays()[i]);
324 }
325 ConfigReady(config);
326}
327
328void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
329 network_thread_->Post(this, MSG_CONFIG_READY, config);
330}
331
332// Adds a configuration to the list.
333void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
334 if (config)
335 configs_.push_back(config);
336
337 AllocatePorts();
338}
339
340void BasicPortAllocatorSession::OnConfigStop() {
341 ASSERT(rtc::Thread::Current() == network_thread_);
342
343 // If any of the allocated ports have not completed the candidates allocation,
344 // mark those as error. Since session doesn't need any new candidates
345 // at this stage of the allocation, it's safe to discard any new candidates.
346 bool send_signal = false;
347 for (std::vector<PortData>::iterator it = ports_.begin();
348 it != ports_.end(); ++it) {
349 if (!it->complete()) {
350 // Updating port state to error, which didn't finish allocating candidates
351 // yet.
352 it->set_error();
353 send_signal = true;
354 }
355 }
356
357 // Did we stop any running sequences?
358 for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
359 it != sequences_.end() && !send_signal; ++it) {
360 if ((*it)->state() == AllocationSequence::kStopped) {
361 send_signal = true;
362 }
363 }
364
365 // If we stopped anything that was running, send a done signal now.
366 if (send_signal) {
367 MaybeSignalCandidatesAllocationDone();
368 }
369}
370
371void BasicPortAllocatorSession::AllocatePorts() {
372 ASSERT(rtc::Thread::Current() == network_thread_);
373 network_thread_->Post(this, MSG_ALLOCATE);
374}
375
376void BasicPortAllocatorSession::OnAllocate() {
377 if (network_manager_started_)
378 DoAllocate();
379
380 allocation_started_ = true;
381}
382
383// For each network, see if we have a sequence that covers it already. If not,
384// create a new sequence to create the appropriate ports.
385void BasicPortAllocatorSession::DoAllocate() {
386 bool done_signal_needed = false;
387 std::vector<rtc::Network*> networks;
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000388
389 // If the adapter enumeration is disabled, we'll just bind to any address
390 // instead of specific NIC. This is to ensure the same routing for http
391 // traffic by OS is also used here to avoid any local or public IP leakage
392 // during stun process.
393 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
394 allocator_->network_manager()->GetAnyAddressNetworks(&networks);
395 } else {
396 allocator_->network_manager()->GetNetworks(&networks);
397 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000398 if (networks.empty()) {
399 LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
400 done_signal_needed = true;
401 } else {
402 for (uint32 i = 0; i < networks.size(); ++i) {
403 PortConfiguration* config = NULL;
404 if (configs_.size() > 0)
405 config = configs_.back();
406
407 uint32 sequence_flags = flags();
408 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
409 // If all the ports are disabled we should just fire the allocation
410 // done event and return.
411 done_signal_needed = true;
412 break;
413 }
414
415 // Disables phases that are not specified in this config.
416 if (!config || config->StunServers().empty()) {
417 // No STUN ports specified in this config.
418 sequence_flags |= PORTALLOCATOR_DISABLE_STUN;
419 }
420 if (!config || config->relays.empty()) {
421 // No relay ports specified in this config.
422 sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
423 }
424
425 if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000426 networks[i]->GetBestIP().family() == AF_INET6) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000427 // Skip IPv6 networks unless the flag's been set.
428 continue;
429 }
430
431 // Disable phases that would only create ports equivalent to
432 // ones that we have already made.
433 DisableEquivalentPhases(networks[i], config, &sequence_flags);
434
435 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
436 // New AllocationSequence would have nothing to do, so don't make it.
437 continue;
438 }
439
440 AllocationSequence* sequence =
441 new AllocationSequence(this, networks[i], config, sequence_flags);
442 if (!sequence->Init()) {
443 delete sequence;
444 continue;
445 }
446 done_signal_needed = true;
447 sequence->SignalPortAllocationComplete.connect(
448 this, &BasicPortAllocatorSession::OnPortAllocationComplete);
449 if (running_)
450 sequence->Start();
451 sequences_.push_back(sequence);
452 }
453 }
454 if (done_signal_needed) {
455 network_thread_->Post(this, MSG_SEQUENCEOBJECTS_CREATED);
456 }
457}
458
459void BasicPortAllocatorSession::OnNetworksChanged() {
460 network_manager_started_ = true;
461 if (allocation_started_)
462 DoAllocate();
463}
464
465void BasicPortAllocatorSession::DisableEquivalentPhases(
466 rtc::Network* network, PortConfiguration* config, uint32* flags) {
467 for (uint32 i = 0; i < sequences_.size() &&
468 (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES; ++i) {
469 sequences_[i]->DisableEquivalentPhases(network, config, flags);
470 }
471}
472
473void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
474 AllocationSequence * seq,
475 bool prepare_address) {
476 if (!port)
477 return;
478
479 LOG(LS_INFO) << "Adding allocated port for " << content_name();
480 port->set_content_name(content_name());
481 port->set_component(component_);
482 port->set_generation(generation());
483 if (allocator_->proxy().type != rtc::PROXY_NONE)
484 port->set_proxy(allocator_->user_agent(), allocator_->proxy());
485 port->set_send_retransmit_count_attribute((allocator_->flags() &
486 PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
487
488 // Push down the candidate_filter to individual port.
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000489 uint32 candidate_filter = allocator_->candidate_filter();
490
491 // When adapter enumeration is disabled, disable CF_HOST at port level so
492 // local address is not leaked by stunport in the candidate's related address.
493 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
494 candidate_filter &= ~CF_HOST;
495 }
496 port->set_candidate_filter(candidate_filter);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000497
498 PortData data(port, seq);
499 ports_.push_back(data);
500
501 port->SignalCandidateReady.connect(
502 this, &BasicPortAllocatorSession::OnCandidateReady);
503 port->SignalPortComplete.connect(this,
504 &BasicPortAllocatorSession::OnPortComplete);
505 port->SignalDestroyed.connect(this,
506 &BasicPortAllocatorSession::OnPortDestroyed);
507 port->SignalPortError.connect(
508 this, &BasicPortAllocatorSession::OnPortError);
509 LOG_J(LS_INFO, port) << "Added port to allocator";
510
511 if (prepare_address)
512 port->PrepareAddress();
513}
514
515void BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
516 allocation_sequences_created_ = true;
517 // Send candidate allocation complete signal if we have no sequences.
518 MaybeSignalCandidatesAllocationDone();
519}
520
521void BasicPortAllocatorSession::OnCandidateReady(
522 Port* port, const Candidate& c) {
523 ASSERT(rtc::Thread::Current() == network_thread_);
524 PortData* data = FindPort(port);
525 ASSERT(data != NULL);
526 // Discarding any candidate signal if port allocation status is
527 // already in completed state.
528 if (data->complete())
529 return;
530
531 // Send candidates whose protocol is enabled.
532 std::vector<Candidate> candidates;
533 ProtocolType pvalue;
534 bool candidate_allowed_to_send = CheckCandidateFilter(c);
535 if (StringToProto(c.protocol().c_str(), &pvalue) &&
536 data->sequence()->ProtocolEnabled(pvalue) &&
537 candidate_allowed_to_send) {
538 candidates.push_back(c);
539 }
540
541 if (!candidates.empty()) {
542 SignalCandidatesReady(this, candidates);
543 }
544
545 // Moving to READY state as we have atleast one candidate from the port.
546 // Since this port has atleast one candidate we should forward this port
547 // to listners, to allow connections from this port.
548 // Also we should make sure that candidate gathered from this port is allowed
549 // to send outside.
550 if (!data->ready() && candidate_allowed_to_send) {
551 data->set_ready();
552 SignalPortReady(this, port);
553 }
554}
555
556void BasicPortAllocatorSession::OnPortComplete(Port* port) {
557 ASSERT(rtc::Thread::Current() == network_thread_);
558 PortData* data = FindPort(port);
559 ASSERT(data != NULL);
560
561 // Ignore any late signals.
562 if (data->complete())
563 return;
564
565 // Moving to COMPLETE state.
566 data->set_complete();
567 // Send candidate allocation complete signal if this was the last port.
568 MaybeSignalCandidatesAllocationDone();
569}
570
571void BasicPortAllocatorSession::OnPortError(Port* port) {
572 ASSERT(rtc::Thread::Current() == network_thread_);
573 PortData* data = FindPort(port);
574 ASSERT(data != NULL);
575 // We might have already given up on this port and stopped it.
576 if (data->complete())
577 return;
578
579 // SignalAddressError is currently sent from StunPort/TurnPort.
580 // But this signal itself is generic.
581 data->set_error();
582 // Send candidate allocation complete signal if this was the last port.
583 MaybeSignalCandidatesAllocationDone();
584}
585
586void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
587 ProtocolType proto) {
588 std::vector<Candidate> candidates;
589 for (std::vector<PortData>::iterator it = ports_.begin();
590 it != ports_.end(); ++it) {
591 if (it->sequence() != seq)
592 continue;
593
594 const std::vector<Candidate>& potentials = it->port()->Candidates();
595 for (size_t i = 0; i < potentials.size(); ++i) {
596 if (!CheckCandidateFilter(potentials[i]))
597 continue;
598 ProtocolType pvalue;
599 if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
600 continue;
601 if (pvalue == proto) {
602 candidates.push_back(potentials[i]);
603 }
604 }
605 }
606
607 if (!candidates.empty()) {
608 SignalCandidatesReady(this, candidates);
609 }
610}
611
612bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) {
613 uint32 filter = allocator_->candidate_filter();
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000614
615 // When binding to any address, before sending packets out, the getsockname
616 // returns all 0s, but after sending packets, it'll be the NIC used to
617 // send. All 0s is not a valid ICE candidate address and should be filtered
618 // out.
619 if (c.address().IsAnyIP()) {
620 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000621 }
622
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000623 if (c.type() == RELAY_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000624 return ((filter & CF_RELAY) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000625 } else if (c.type() == STUN_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000626 return ((filter & CF_REFLEXIVE) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000627 } else if (c.type() == LOCAL_PORT_TYPE) {
628 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
629 // We allow host candidates if the filter allows server-reflexive
630 // candidates and the candidate is a public IP. Because we don't generate
631 // server-reflexive candidates if they have the same IP as the host
632 // candidate (i.e. when the host candidate is a public IP), filtering to
633 // only server-reflexive candidates won't work right when the host
634 // candidates have public IPs.
635 return true;
636 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000637
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000638 // This is just to prevent the case when binding to any address (all 0s), if
639 // somehow the host candidate address is not all 0s. Either because local
640 // installed proxy changes the address or a packet has been sent for any
641 // reason before getsockname is called.
642 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
643 LOG(LS_WARNING) << "Received non-0 host address: "
644 << c.address().ToString()
645 << " when adapter enumeration is disabled";
646 return false;
647 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000648
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000649 return ((filter & CF_HOST) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000650 }
651 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000652}
653
654void BasicPortAllocatorSession::OnPortAllocationComplete(
655 AllocationSequence* seq) {
656 // Send candidate allocation complete signal if all ports are done.
657 MaybeSignalCandidatesAllocationDone();
658}
659
660void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
661 // Send signal only if all required AllocationSequence objects
662 // are created.
663 if (!allocation_sequences_created_)
664 return;
665
666 // Check that all port allocation sequences are complete.
667 for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
668 it != sequences_.end(); ++it) {
669 if ((*it)->state() == AllocationSequence::kRunning)
670 return;
671 }
672
673 // If all allocated ports are in complete state, session must have got all
674 // expected candidates. Session will trigger candidates allocation complete
675 // signal.
676 for (std::vector<PortData>::iterator it = ports_.begin();
677 it != ports_.end(); ++it) {
678 if (!it->complete())
679 return;
680 }
681 LOG(LS_INFO) << "All candidates gathered for " << content_name_ << ":"
682 << component_ << ":" << generation();
683 SignalCandidatesAllocationDone(this);
684}
685
686void BasicPortAllocatorSession::OnPortDestroyed(
687 PortInterface* port) {
688 ASSERT(rtc::Thread::Current() == network_thread_);
689 for (std::vector<PortData>::iterator iter = ports_.begin();
690 iter != ports_.end(); ++iter) {
691 if (port == iter->port()) {
692 ports_.erase(iter);
693 LOG_J(LS_INFO, port) << "Removed port from allocator ("
694 << static_cast<int>(ports_.size()) << " remaining)";
695 return;
696 }
697 }
698 ASSERT(false);
699}
700
701void BasicPortAllocatorSession::OnShake() {
702 LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";
703
704 std::vector<Port*> ports;
705 std::vector<Connection*> connections;
706
707 for (size_t i = 0; i < ports_.size(); ++i) {
708 if (ports_[i].ready())
709 ports.push_back(ports_[i].port());
710 }
711
712 for (size_t i = 0; i < ports.size(); ++i) {
713 Port::AddressMap::const_iterator iter;
714 for (iter = ports[i]->connections().begin();
715 iter != ports[i]->connections().end();
716 ++iter) {
717 connections.push_back(iter->second);
718 }
719 }
720
721 LOG(INFO) << ">>>>> Destroying " << ports.size() << " ports and "
722 << connections.size() << " connections";
723
724 for (size_t i = 0; i < connections.size(); ++i)
725 connections[i]->Destroy();
726
727 if (running_ || (ports.size() > 0) || (connections.size() > 0))
728 network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
729}
730
731BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
732 Port* port) {
733 for (std::vector<PortData>::iterator it = ports_.begin();
734 it != ports_.end(); ++it) {
735 if (it->port() == port) {
736 return &*it;
737 }
738 }
739 return NULL;
740}
741
742// AllocationSequence
743
744AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
745 rtc::Network* network,
746 PortConfiguration* config,
747 uint32 flags)
748 : session_(session),
749 network_(network),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000750 ip_(network->GetBestIP()),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000751 config_(config),
752 state_(kInit),
753 flags_(flags),
754 udp_socket_(),
755 udp_port_(NULL),
756 phase_(0) {
757}
758
759bool AllocationSequence::Init() {
760 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
761 !IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_UFRAG)) {
762 LOG(LS_ERROR) << "Shared socket option can't be set without "
763 << "shared ufrag.";
764 ASSERT(false);
765 return false;
766 }
767
768 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
769 udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
770 rtc::SocketAddress(ip_, 0), session_->allocator()->min_port(),
771 session_->allocator()->max_port()));
772 if (udp_socket_) {
773 udp_socket_->SignalReadPacket.connect(
774 this, &AllocationSequence::OnReadPacket);
775 }
776 // Continuing if |udp_socket_| is NULL, as local TCP and RelayPort using TCP
777 // are next available options to setup a communication channel.
778 }
779 return true;
780}
781
782void AllocationSequence::Clear() {
783 udp_port_ = NULL;
784 turn_ports_.clear();
785}
786
787AllocationSequence::~AllocationSequence() {
788 session_->network_thread()->Clear(this);
789}
790
791void AllocationSequence::DisableEquivalentPhases(rtc::Network* network,
792 PortConfiguration* config, uint32* flags) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000793 if (!((network == network_) && (ip_ == network->GetBestIP()))) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000794 // Different network setup; nothing is equivalent.
795 return;
796 }
797
798 // Else turn off the stuff that we've already got covered.
799
800 // Every config implicitly specifies local, so turn that off right away.
801 *flags |= PORTALLOCATOR_DISABLE_UDP;
802 *flags |= PORTALLOCATOR_DISABLE_TCP;
803
804 if (config_ && config) {
805 if (config_->StunServers() == config->StunServers()) {
806 // Already got this STUN servers covered.
807 *flags |= PORTALLOCATOR_DISABLE_STUN;
808 }
809 if (!config_->relays.empty()) {
810 // Already got relays covered.
811 // NOTE: This will even skip a _different_ set of relay servers if we
812 // were to be given one, but that never happens in our codebase. Should
813 // probably get rid of the list in PortConfiguration and just keep a
814 // single relay server in each one.
815 *flags |= PORTALLOCATOR_DISABLE_RELAY;
816 }
817 }
818}
819
820void AllocationSequence::Start() {
821 state_ = kRunning;
822 session_->network_thread()->Post(this, MSG_ALLOCATION_PHASE);
823}
824
825void AllocationSequence::Stop() {
826 // If the port is completed, don't set it to stopped.
827 if (state_ == kRunning) {
828 state_ = kStopped;
829 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
830 }
831}
832
833void AllocationSequence::OnMessage(rtc::Message* msg) {
834 ASSERT(rtc::Thread::Current() == session_->network_thread());
835 ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
836
837 const char* const PHASE_NAMES[kNumPhases] = {
838 "Udp", "Relay", "Tcp", "SslTcp"
839 };
840
841 // Perform all of the phases in the current step.
842 LOG_J(LS_INFO, network_) << "Allocation Phase="
843 << PHASE_NAMES[phase_];
844
845 switch (phase_) {
846 case PHASE_UDP:
847 CreateUDPPorts();
848 CreateStunPorts();
849 EnableProtocol(PROTO_UDP);
850 break;
851
852 case PHASE_RELAY:
853 CreateRelayPorts();
854 break;
855
856 case PHASE_TCP:
857 CreateTCPPorts();
858 EnableProtocol(PROTO_TCP);
859 break;
860
861 case PHASE_SSLTCP:
862 state_ = kCompleted;
863 EnableProtocol(PROTO_SSLTCP);
864 break;
865
866 default:
867 ASSERT(false);
868 }
869
870 if (state() == kRunning) {
871 ++phase_;
872 session_->network_thread()->PostDelayed(
873 session_->allocator()->step_delay(),
874 this, MSG_ALLOCATION_PHASE);
875 } else {
876 // If all phases in AllocationSequence are completed, no allocation
877 // steps needed further. Canceling pending signal.
878 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
879 SignalPortAllocationComplete(this);
880 }
881}
882
883void AllocationSequence::EnableProtocol(ProtocolType proto) {
884 if (!ProtocolEnabled(proto)) {
885 protocols_.push_back(proto);
886 session_->OnProtocolEnabled(this, proto);
887 }
888}
889
890bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
891 for (ProtocolList::const_iterator it = protocols_.begin();
892 it != protocols_.end(); ++it) {
893 if (*it == proto)
894 return true;
895 }
896 return false;
897}
898
899void AllocationSequence::CreateUDPPorts() {
900 if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
901 LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
902 return;
903 }
904
905 // TODO(mallinath) - Remove UDPPort creating socket after shared socket
906 // is enabled completely.
907 UDPPort* port = NULL;
908 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
909 port = UDPPort::Create(session_->network_thread(),
910 session_->socket_factory(), network_,
911 udp_socket_.get(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000912 session_->username(), session_->password(),
913 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000914 } else {
915 port = UDPPort::Create(session_->network_thread(),
916 session_->socket_factory(),
917 network_, ip_,
918 session_->allocator()->min_port(),
919 session_->allocator()->max_port(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000920 session_->username(), session_->password(),
921 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000922 }
923
924 if (port) {
925 // If shared socket is enabled, STUN candidate will be allocated by the
926 // UDPPort.
927 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
928 udp_port_ = port;
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +0000929 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000930
931 // If STUN is not disabled, setting stun server address to port.
932 if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
933 // If config has stun_servers, use it to get server reflexive candidate
934 // otherwise use first TURN server which supports UDP.
935 if (config_ && !config_->StunServers().empty()) {
936 LOG(LS_INFO) << "AllocationSequence: UDPPort will be handling the "
937 << "STUN candidate generation.";
938 port->set_server_addresses(config_->StunServers());
939 } else if (config_ &&
940 config_->SupportsProtocol(RELAY_TURN, PROTO_UDP)) {
941 port->set_server_addresses(config_->GetRelayServerAddresses(
942 RELAY_TURN, PROTO_UDP));
943 LOG(LS_INFO) << "AllocationSequence: TURN Server address will be "
944 << " used for generating STUN candidate.";
945 }
946 }
947 }
948
949 session_->AddAllocatedPort(port, this, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000950 }
951}
952
953void AllocationSequence::CreateTCPPorts() {
954 if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
955 LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
956 return;
957 }
958
959 Port* port = TCPPort::Create(session_->network_thread(),
960 session_->socket_factory(),
961 network_, ip_,
962 session_->allocator()->min_port(),
963 session_->allocator()->max_port(),
964 session_->username(), session_->password(),
965 session_->allocator()->allow_tcp_listen());
966 if (port) {
967 session_->AddAllocatedPort(port, this, true);
968 // Since TCPPort is not created using shared socket, |port| will not be
969 // added to the dequeue.
970 }
971}
972
973void AllocationSequence::CreateStunPorts() {
974 if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
975 LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
976 return;
977 }
978
979 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
980 return;
981 }
982
983 // If BasicPortAllocatorSession::OnAllocate left STUN ports enabled then we
984 // ought to have an address for them here.
985 ASSERT(config_ && !config_->StunServers().empty());
986 if (!(config_ && !config_->StunServers().empty())) {
987 LOG(LS_WARNING)
988 << "AllocationSequence: No STUN server configured, skipping.";
989 return;
990 }
991
992 StunPort* port = StunPort::Create(session_->network_thread(),
993 session_->socket_factory(),
994 network_, ip_,
995 session_->allocator()->min_port(),
996 session_->allocator()->max_port(),
997 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000998 config_->StunServers(),
999 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001000 if (port) {
1001 session_->AddAllocatedPort(port, this, true);
1002 // Since StunPort is not created using shared socket, |port| will not be
1003 // added to the dequeue.
1004 }
1005}
1006
1007void AllocationSequence::CreateRelayPorts() {
1008 if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
1009 LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
1010 return;
1011 }
1012
1013 // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
1014 // ought to have a relay list for them here.
1015 ASSERT(config_ && !config_->relays.empty());
1016 if (!(config_ && !config_->relays.empty())) {
1017 LOG(LS_WARNING)
1018 << "AllocationSequence: No relay server configured, skipping.";
1019 return;
1020 }
1021
1022 PortConfiguration::RelayList::const_iterator relay;
1023 for (relay = config_->relays.begin();
1024 relay != config_->relays.end(); ++relay) {
1025 if (relay->type == RELAY_GTURN) {
1026 CreateGturnPort(*relay);
1027 } else if (relay->type == RELAY_TURN) {
1028 CreateTurnPort(*relay);
1029 } else {
1030 ASSERT(false);
1031 }
1032 }
1033}
1034
1035void AllocationSequence::CreateGturnPort(const RelayServerConfig& config) {
1036 // TODO(mallinath) - Rename RelayPort to GTurnPort.
1037 RelayPort* port = RelayPort::Create(session_->network_thread(),
1038 session_->socket_factory(),
1039 network_, ip_,
1040 session_->allocator()->min_port(),
1041 session_->allocator()->max_port(),
1042 config_->username, config_->password);
1043 if (port) {
1044 // Since RelayPort is not created using shared socket, |port| will not be
1045 // added to the dequeue.
1046 // Note: We must add the allocated port before we add addresses because
1047 // the latter will create candidates that need name and preference
1048 // settings. However, we also can't prepare the address (normally
1049 // done by AddAllocatedPort) until we have these addresses. So we
1050 // wait to do that until below.
1051 session_->AddAllocatedPort(port, this, false);
1052
1053 // Add the addresses of this protocol.
1054 PortList::const_iterator relay_port;
1055 for (relay_port = config.ports.begin();
1056 relay_port != config.ports.end();
1057 ++relay_port) {
1058 port->AddServerAddress(*relay_port);
1059 port->AddExternalAddress(*relay_port);
1060 }
1061 // Start fetching an address for this port.
1062 port->PrepareAddress();
1063 }
1064}
1065
1066void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
1067 PortList::const_iterator relay_port;
1068 for (relay_port = config.ports.begin();
1069 relay_port != config.ports.end(); ++relay_port) {
1070 TurnPort* port = NULL;
1071 // Shared socket mode must be enabled only for UDP based ports. Hence
1072 // don't pass shared socket for ports which will create TCP sockets.
1073 // TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
1074 // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
1075 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
1076 relay_port->proto == PROTO_UDP) {
1077 port = TurnPort::Create(session_->network_thread(),
1078 session_->socket_factory(),
1079 network_, udp_socket_.get(),
1080 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001081 *relay_port, config.credentials, config.priority,
1082 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001083 turn_ports_.push_back(port);
1084 // Listen to the port destroyed signal, to allow AllocationSequence to
1085 // remove entrt from it's map.
1086 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
1087 } else {
1088 port = TurnPort::Create(session_->network_thread(),
1089 session_->socket_factory(),
1090 network_, ip_,
1091 session_->allocator()->min_port(),
1092 session_->allocator()->max_port(),
1093 session_->username(),
1094 session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001095 *relay_port, config.credentials, config.priority,
1096 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001097 }
1098 ASSERT(port != NULL);
1099 session_->AddAllocatedPort(port, this, true);
1100 }
1101}
1102
1103void AllocationSequence::OnReadPacket(
1104 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
1105 const rtc::SocketAddress& remote_addr,
1106 const rtc::PacketTime& packet_time) {
1107 ASSERT(socket == udp_socket_.get());
1108
1109 bool turn_port_found = false;
1110
1111 // Try to find the TurnPort that matches the remote address. Note that the
1112 // message could be a STUN binding response if the TURN server is also used as
1113 // a STUN server. We don't want to parse every message here to check if it is
1114 // a STUN binding response, so we pass the message to TurnPort regardless of
1115 // the message type. The TurnPort will just ignore the message since it will
1116 // not find any request by transaction ID.
1117 for (std::vector<TurnPort*>::const_iterator it = turn_ports_.begin();
1118 it != turn_ports_.end(); ++it) {
1119 TurnPort* port = *it;
1120 if (port->server_address().address == remote_addr) {
1121 port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
1122 turn_port_found = true;
1123 break;
1124 }
1125 }
1126
1127 if (udp_port_) {
1128 const ServerAddresses& stun_servers = udp_port_->server_addresses();
1129
1130 // Pass the packet to the UdpPort if there is no matching TurnPort, or if
1131 // the TURN server is also a STUN server.
1132 if (!turn_port_found ||
1133 stun_servers.find(remote_addr) != stun_servers.end()) {
1134 udp_port_->HandleIncomingPacket(
1135 socket, data, size, remote_addr, packet_time);
1136 }
1137 }
1138}
1139
1140void AllocationSequence::OnPortDestroyed(PortInterface* port) {
1141 if (udp_port_ == port) {
1142 udp_port_ = NULL;
1143 return;
1144 }
1145
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +00001146 auto it = std::find(turn_ports_.begin(), turn_ports_.end(), port);
1147 if (it != turn_ports_.end()) {
1148 turn_ports_.erase(it);
1149 } else {
1150 LOG(LS_ERROR) << "Unexpected OnPortDestroyed for nonexistent port.";
1151 ASSERT(false);
1152 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001153}
1154
1155// PortConfiguration
1156PortConfiguration::PortConfiguration(
1157 const rtc::SocketAddress& stun_address,
1158 const std::string& username,
1159 const std::string& password)
1160 : stun_address(stun_address), username(username), password(password) {
1161 if (!stun_address.IsNil())
1162 stun_servers.insert(stun_address);
1163}
1164
1165PortConfiguration::PortConfiguration(const ServerAddresses& stun_servers,
1166 const std::string& username,
1167 const std::string& password)
1168 : stun_servers(stun_servers),
1169 username(username),
1170 password(password) {
1171 if (!stun_servers.empty())
1172 stun_address = *(stun_servers.begin());
1173}
1174
1175ServerAddresses PortConfiguration::StunServers() {
1176 if (!stun_address.IsNil() &&
1177 stun_servers.find(stun_address) == stun_servers.end()) {
1178 stun_servers.insert(stun_address);
1179 }
1180 return stun_servers;
1181}
1182
1183void PortConfiguration::AddRelay(const RelayServerConfig& config) {
1184 relays.push_back(config);
1185}
1186
1187bool PortConfiguration::SupportsProtocol(
1188 const RelayServerConfig& relay, ProtocolType type) const {
1189 PortList::const_iterator relay_port;
1190 for (relay_port = relay.ports.begin();
1191 relay_port != relay.ports.end();
1192 ++relay_port) {
1193 if (relay_port->proto == type)
1194 return true;
1195 }
1196 return false;
1197}
1198
1199bool PortConfiguration::SupportsProtocol(RelayType turn_type,
1200 ProtocolType type) const {
1201 for (size_t i = 0; i < relays.size(); ++i) {
1202 if (relays[i].type == turn_type &&
1203 SupportsProtocol(relays[i], type))
1204 return true;
1205 }
1206 return false;
1207}
1208
1209ServerAddresses PortConfiguration::GetRelayServerAddresses(
1210 RelayType turn_type, ProtocolType type) const {
1211 ServerAddresses servers;
1212 for (size_t i = 0; i < relays.size(); ++i) {
1213 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1214 servers.insert(relays[i].ports.front().address);
1215 }
1216 }
1217 return servers;
1218}
1219
1220} // namespace cricket