blob: 41edd85e9eb9ff5e901ad0baa75188da4888d6af [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
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000415 if (!config || config->relays.empty()) {
416 // No relay ports specified in this config.
417 sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
418 }
419
420 if (!(sequence_flags & PORTALLOCATOR_ENABLE_IPV6) &&
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000421 networks[i]->GetBestIP().family() == AF_INET6) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000422 // Skip IPv6 networks unless the flag's been set.
423 continue;
424 }
425
426 // Disable phases that would only create ports equivalent to
427 // ones that we have already made.
428 DisableEquivalentPhases(networks[i], config, &sequence_flags);
429
430 if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
431 // New AllocationSequence would have nothing to do, so don't make it.
432 continue;
433 }
434
435 AllocationSequence* sequence =
436 new AllocationSequence(this, networks[i], config, sequence_flags);
437 if (!sequence->Init()) {
438 delete sequence;
439 continue;
440 }
441 done_signal_needed = true;
442 sequence->SignalPortAllocationComplete.connect(
443 this, &BasicPortAllocatorSession::OnPortAllocationComplete);
444 if (running_)
445 sequence->Start();
446 sequences_.push_back(sequence);
447 }
448 }
449 if (done_signal_needed) {
450 network_thread_->Post(this, MSG_SEQUENCEOBJECTS_CREATED);
451 }
452}
453
454void BasicPortAllocatorSession::OnNetworksChanged() {
455 network_manager_started_ = true;
456 if (allocation_started_)
457 DoAllocate();
458}
459
460void BasicPortAllocatorSession::DisableEquivalentPhases(
461 rtc::Network* network, PortConfiguration* config, uint32* flags) {
462 for (uint32 i = 0; i < sequences_.size() &&
463 (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES; ++i) {
464 sequences_[i]->DisableEquivalentPhases(network, config, flags);
465 }
466}
467
468void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
469 AllocationSequence * seq,
470 bool prepare_address) {
471 if (!port)
472 return;
473
474 LOG(LS_INFO) << "Adding allocated port for " << content_name();
475 port->set_content_name(content_name());
476 port->set_component(component_);
477 port->set_generation(generation());
478 if (allocator_->proxy().type != rtc::PROXY_NONE)
479 port->set_proxy(allocator_->user_agent(), allocator_->proxy());
480 port->set_send_retransmit_count_attribute((allocator_->flags() &
481 PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
482
483 // Push down the candidate_filter to individual port.
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000484 uint32 candidate_filter = allocator_->candidate_filter();
485
486 // When adapter enumeration is disabled, disable CF_HOST at port level so
487 // local address is not leaked by stunport in the candidate's related address.
488 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
489 candidate_filter &= ~CF_HOST;
490 }
491 port->set_candidate_filter(candidate_filter);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000492
493 PortData data(port, seq);
494 ports_.push_back(data);
495
496 port->SignalCandidateReady.connect(
497 this, &BasicPortAllocatorSession::OnCandidateReady);
498 port->SignalPortComplete.connect(this,
499 &BasicPortAllocatorSession::OnPortComplete);
500 port->SignalDestroyed.connect(this,
501 &BasicPortAllocatorSession::OnPortDestroyed);
502 port->SignalPortError.connect(
503 this, &BasicPortAllocatorSession::OnPortError);
504 LOG_J(LS_INFO, port) << "Added port to allocator";
505
506 if (prepare_address)
507 port->PrepareAddress();
508}
509
510void BasicPortAllocatorSession::OnAllocationSequenceObjectsCreated() {
511 allocation_sequences_created_ = true;
512 // Send candidate allocation complete signal if we have no sequences.
513 MaybeSignalCandidatesAllocationDone();
514}
515
516void BasicPortAllocatorSession::OnCandidateReady(
517 Port* port, const Candidate& c) {
518 ASSERT(rtc::Thread::Current() == network_thread_);
519 PortData* data = FindPort(port);
520 ASSERT(data != NULL);
521 // Discarding any candidate signal if port allocation status is
522 // already in completed state.
523 if (data->complete())
524 return;
525
526 // Send candidates whose protocol is enabled.
527 std::vector<Candidate> candidates;
528 ProtocolType pvalue;
529 bool candidate_allowed_to_send = CheckCandidateFilter(c);
530 if (StringToProto(c.protocol().c_str(), &pvalue) &&
531 data->sequence()->ProtocolEnabled(pvalue) &&
532 candidate_allowed_to_send) {
533 candidates.push_back(c);
534 }
535
536 if (!candidates.empty()) {
537 SignalCandidatesReady(this, candidates);
538 }
539
540 // Moving to READY state as we have atleast one candidate from the port.
541 // Since this port has atleast one candidate we should forward this port
542 // to listners, to allow connections from this port.
543 // Also we should make sure that candidate gathered from this port is allowed
544 // to send outside.
545 if (!data->ready() && candidate_allowed_to_send) {
546 data->set_ready();
547 SignalPortReady(this, port);
548 }
549}
550
551void BasicPortAllocatorSession::OnPortComplete(Port* port) {
552 ASSERT(rtc::Thread::Current() == network_thread_);
553 PortData* data = FindPort(port);
554 ASSERT(data != NULL);
555
556 // Ignore any late signals.
557 if (data->complete())
558 return;
559
560 // Moving to COMPLETE state.
561 data->set_complete();
562 // Send candidate allocation complete signal if this was the last port.
563 MaybeSignalCandidatesAllocationDone();
564}
565
566void BasicPortAllocatorSession::OnPortError(Port* port) {
567 ASSERT(rtc::Thread::Current() == network_thread_);
568 PortData* data = FindPort(port);
569 ASSERT(data != NULL);
570 // We might have already given up on this port and stopped it.
571 if (data->complete())
572 return;
573
574 // SignalAddressError is currently sent from StunPort/TurnPort.
575 // But this signal itself is generic.
576 data->set_error();
577 // Send candidate allocation complete signal if this was the last port.
578 MaybeSignalCandidatesAllocationDone();
579}
580
581void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq,
582 ProtocolType proto) {
583 std::vector<Candidate> candidates;
584 for (std::vector<PortData>::iterator it = ports_.begin();
585 it != ports_.end(); ++it) {
586 if (it->sequence() != seq)
587 continue;
588
589 const std::vector<Candidate>& potentials = it->port()->Candidates();
590 for (size_t i = 0; i < potentials.size(); ++i) {
591 if (!CheckCandidateFilter(potentials[i]))
592 continue;
593 ProtocolType pvalue;
594 if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
595 continue;
596 if (pvalue == proto) {
597 candidates.push_back(potentials[i]);
598 }
599 }
600 }
601
602 if (!candidates.empty()) {
603 SignalCandidatesReady(this, candidates);
604 }
605}
606
607bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) {
608 uint32 filter = allocator_->candidate_filter();
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000609
610 // When binding to any address, before sending packets out, the getsockname
611 // returns all 0s, but after sending packets, it'll be the NIC used to
612 // send. All 0s is not a valid ICE candidate address and should be filtered
613 // out.
614 if (c.address().IsAnyIP()) {
615 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000616 }
617
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000618 if (c.type() == RELAY_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000619 return ((filter & CF_RELAY) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000620 } else if (c.type() == STUN_PORT_TYPE) {
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000621 return ((filter & CF_REFLEXIVE) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000622 } else if (c.type() == LOCAL_PORT_TYPE) {
623 if ((filter & CF_REFLEXIVE) && !c.address().IsPrivateIP()) {
624 // We allow host candidates if the filter allows server-reflexive
625 // candidates and the candidate is a public IP. Because we don't generate
626 // server-reflexive candidates if they have the same IP as the host
627 // candidate (i.e. when the host candidate is a public IP), filtering to
628 // only server-reflexive candidates won't work right when the host
629 // candidates have public IPs.
630 return true;
631 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000632
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000633 // This is just to prevent the case when binding to any address (all 0s), if
634 // somehow the host candidate address is not all 0s. Either because local
635 // installed proxy changes the address or a packet has been sent for any
636 // reason before getsockname is called.
637 if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
638 LOG(LS_WARNING) << "Received non-0 host address: "
639 << c.address().ToString()
640 << " when adapter enumeration is disabled";
641 return false;
642 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000643
guoweis@webrtc.org931e0cf2015-02-18 19:09:42 +0000644 return ((filter & CF_HOST) != 0);
guoweis@webrtc.orgf358aea2015-02-18 18:44:01 +0000645 }
646 return false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000647}
648
649void BasicPortAllocatorSession::OnPortAllocationComplete(
650 AllocationSequence* seq) {
651 // Send candidate allocation complete signal if all ports are done.
652 MaybeSignalCandidatesAllocationDone();
653}
654
655void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() {
656 // Send signal only if all required AllocationSequence objects
657 // are created.
658 if (!allocation_sequences_created_)
659 return;
660
661 // Check that all port allocation sequences are complete.
662 for (std::vector<AllocationSequence*>::iterator it = sequences_.begin();
663 it != sequences_.end(); ++it) {
664 if ((*it)->state() == AllocationSequence::kRunning)
665 return;
666 }
667
668 // If all allocated ports are in complete state, session must have got all
669 // expected candidates. Session will trigger candidates allocation complete
670 // signal.
671 for (std::vector<PortData>::iterator it = ports_.begin();
672 it != ports_.end(); ++it) {
673 if (!it->complete())
674 return;
675 }
676 LOG(LS_INFO) << "All candidates gathered for " << content_name_ << ":"
677 << component_ << ":" << generation();
678 SignalCandidatesAllocationDone(this);
679}
680
681void BasicPortAllocatorSession::OnPortDestroyed(
682 PortInterface* port) {
683 ASSERT(rtc::Thread::Current() == network_thread_);
684 for (std::vector<PortData>::iterator iter = ports_.begin();
685 iter != ports_.end(); ++iter) {
686 if (port == iter->port()) {
687 ports_.erase(iter);
688 LOG_J(LS_INFO, port) << "Removed port from allocator ("
689 << static_cast<int>(ports_.size()) << " remaining)";
690 return;
691 }
692 }
693 ASSERT(false);
694}
695
696void BasicPortAllocatorSession::OnShake() {
697 LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";
698
699 std::vector<Port*> ports;
700 std::vector<Connection*> connections;
701
702 for (size_t i = 0; i < ports_.size(); ++i) {
703 if (ports_[i].ready())
704 ports.push_back(ports_[i].port());
705 }
706
707 for (size_t i = 0; i < ports.size(); ++i) {
708 Port::AddressMap::const_iterator iter;
709 for (iter = ports[i]->connections().begin();
710 iter != ports[i]->connections().end();
711 ++iter) {
712 connections.push_back(iter->second);
713 }
714 }
715
716 LOG(INFO) << ">>>>> Destroying " << ports.size() << " ports and "
717 << connections.size() << " connections";
718
719 for (size_t i = 0; i < connections.size(); ++i)
720 connections[i]->Destroy();
721
722 if (running_ || (ports.size() > 0) || (connections.size() > 0))
723 network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
724}
725
726BasicPortAllocatorSession::PortData* BasicPortAllocatorSession::FindPort(
727 Port* port) {
728 for (std::vector<PortData>::iterator it = ports_.begin();
729 it != ports_.end(); ++it) {
730 if (it->port() == port) {
731 return &*it;
732 }
733 }
734 return NULL;
735}
736
737// AllocationSequence
738
739AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
740 rtc::Network* network,
741 PortConfiguration* config,
742 uint32 flags)
743 : session_(session),
744 network_(network),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000745 ip_(network->GetBestIP()),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000746 config_(config),
747 state_(kInit),
748 flags_(flags),
749 udp_socket_(),
750 udp_port_(NULL),
751 phase_(0) {
752}
753
754bool AllocationSequence::Init() {
755 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
756 !IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_UFRAG)) {
757 LOG(LS_ERROR) << "Shared socket option can't be set without "
758 << "shared ufrag.";
759 ASSERT(false);
760 return false;
761 }
762
763 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
764 udp_socket_.reset(session_->socket_factory()->CreateUdpSocket(
765 rtc::SocketAddress(ip_, 0), session_->allocator()->min_port(),
766 session_->allocator()->max_port()));
767 if (udp_socket_) {
768 udp_socket_->SignalReadPacket.connect(
769 this, &AllocationSequence::OnReadPacket);
770 }
771 // Continuing if |udp_socket_| is NULL, as local TCP and RelayPort using TCP
772 // are next available options to setup a communication channel.
773 }
774 return true;
775}
776
777void AllocationSequence::Clear() {
778 udp_port_ = NULL;
779 turn_ports_.clear();
780}
781
782AllocationSequence::~AllocationSequence() {
783 session_->network_thread()->Clear(this);
784}
785
786void AllocationSequence::DisableEquivalentPhases(rtc::Network* network,
787 PortConfiguration* config, uint32* flags) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000788 if (!((network == network_) && (ip_ == network->GetBestIP()))) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000789 // Different network setup; nothing is equivalent.
790 return;
791 }
792
793 // Else turn off the stuff that we've already got covered.
794
795 // Every config implicitly specifies local, so turn that off right away.
796 *flags |= PORTALLOCATOR_DISABLE_UDP;
797 *flags |= PORTALLOCATOR_DISABLE_TCP;
798
799 if (config_ && config) {
800 if (config_->StunServers() == config->StunServers()) {
801 // Already got this STUN servers covered.
802 *flags |= PORTALLOCATOR_DISABLE_STUN;
803 }
804 if (!config_->relays.empty()) {
805 // Already got relays covered.
806 // NOTE: This will even skip a _different_ set of relay servers if we
807 // were to be given one, but that never happens in our codebase. Should
808 // probably get rid of the list in PortConfiguration and just keep a
809 // single relay server in each one.
810 *flags |= PORTALLOCATOR_DISABLE_RELAY;
811 }
812 }
813}
814
815void AllocationSequence::Start() {
816 state_ = kRunning;
817 session_->network_thread()->Post(this, MSG_ALLOCATION_PHASE);
818}
819
820void AllocationSequence::Stop() {
821 // If the port is completed, don't set it to stopped.
822 if (state_ == kRunning) {
823 state_ = kStopped;
824 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
825 }
826}
827
828void AllocationSequence::OnMessage(rtc::Message* msg) {
829 ASSERT(rtc::Thread::Current() == session_->network_thread());
830 ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);
831
832 const char* const PHASE_NAMES[kNumPhases] = {
833 "Udp", "Relay", "Tcp", "SslTcp"
834 };
835
836 // Perform all of the phases in the current step.
837 LOG_J(LS_INFO, network_) << "Allocation Phase="
838 << PHASE_NAMES[phase_];
839
840 switch (phase_) {
841 case PHASE_UDP:
842 CreateUDPPorts();
843 CreateStunPorts();
844 EnableProtocol(PROTO_UDP);
845 break;
846
847 case PHASE_RELAY:
848 CreateRelayPorts();
849 break;
850
851 case PHASE_TCP:
852 CreateTCPPorts();
853 EnableProtocol(PROTO_TCP);
854 break;
855
856 case PHASE_SSLTCP:
857 state_ = kCompleted;
858 EnableProtocol(PROTO_SSLTCP);
859 break;
860
861 default:
862 ASSERT(false);
863 }
864
865 if (state() == kRunning) {
866 ++phase_;
867 session_->network_thread()->PostDelayed(
868 session_->allocator()->step_delay(),
869 this, MSG_ALLOCATION_PHASE);
870 } else {
871 // If all phases in AllocationSequence are completed, no allocation
872 // steps needed further. Canceling pending signal.
873 session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
874 SignalPortAllocationComplete(this);
875 }
876}
877
878void AllocationSequence::EnableProtocol(ProtocolType proto) {
879 if (!ProtocolEnabled(proto)) {
880 protocols_.push_back(proto);
881 session_->OnProtocolEnabled(this, proto);
882 }
883}
884
885bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
886 for (ProtocolList::const_iterator it = protocols_.begin();
887 it != protocols_.end(); ++it) {
888 if (*it == proto)
889 return true;
890 }
891 return false;
892}
893
894void AllocationSequence::CreateUDPPorts() {
895 if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP)) {
896 LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
897 return;
898 }
899
900 // TODO(mallinath) - Remove UDPPort creating socket after shared socket
901 // is enabled completely.
902 UDPPort* port = NULL;
903 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
904 port = UDPPort::Create(session_->network_thread(),
905 session_->socket_factory(), network_,
906 udp_socket_.get(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000907 session_->username(), session_->password(),
908 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000909 } else {
910 port = UDPPort::Create(session_->network_thread(),
911 session_->socket_factory(),
912 network_, ip_,
913 session_->allocator()->min_port(),
914 session_->allocator()->max_port(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000915 session_->username(), session_->password(),
916 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000917 }
918
919 if (port) {
920 // If shared socket is enabled, STUN candidate will be allocated by the
921 // UDPPort.
922 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
923 udp_port_ = port;
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +0000924 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000925
926 // If STUN is not disabled, setting stun server address to port.
927 if (!IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
928 // If config has stun_servers, use it to get server reflexive candidate
929 // otherwise use first TURN server which supports UDP.
930 if (config_ && !config_->StunServers().empty()) {
931 LOG(LS_INFO) << "AllocationSequence: UDPPort will be handling the "
932 << "STUN candidate generation.";
933 port->set_server_addresses(config_->StunServers());
934 } else if (config_ &&
935 config_->SupportsProtocol(RELAY_TURN, PROTO_UDP)) {
936 port->set_server_addresses(config_->GetRelayServerAddresses(
937 RELAY_TURN, PROTO_UDP));
938 LOG(LS_INFO) << "AllocationSequence: TURN Server address will be "
939 << " used for generating STUN candidate.";
940 }
941 }
942 }
943
944 session_->AddAllocatedPort(port, this, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000945 }
946}
947
948void AllocationSequence::CreateTCPPorts() {
949 if (IsFlagSet(PORTALLOCATOR_DISABLE_TCP)) {
950 LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
951 return;
952 }
953
954 Port* port = TCPPort::Create(session_->network_thread(),
955 session_->socket_factory(),
956 network_, ip_,
957 session_->allocator()->min_port(),
958 session_->allocator()->max_port(),
959 session_->username(), session_->password(),
960 session_->allocator()->allow_tcp_listen());
961 if (port) {
962 session_->AddAllocatedPort(port, this, true);
963 // Since TCPPort is not created using shared socket, |port| will not be
964 // added to the dequeue.
965 }
966}
967
968void AllocationSequence::CreateStunPorts() {
969 if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
970 LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
971 return;
972 }
973
974 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) {
975 return;
976 }
977
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000978 if (!(config_ && !config_->StunServers().empty())) {
979 LOG(LS_WARNING)
980 << "AllocationSequence: No STUN server configured, skipping.";
981 return;
982 }
983
984 StunPort* port = StunPort::Create(session_->network_thread(),
985 session_->socket_factory(),
986 network_, ip_,
987 session_->allocator()->min_port(),
988 session_->allocator()->max_port(),
989 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000990 config_->StunServers(),
991 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000992 if (port) {
993 session_->AddAllocatedPort(port, this, true);
994 // Since StunPort is not created using shared socket, |port| will not be
995 // added to the dequeue.
996 }
997}
998
999void AllocationSequence::CreateRelayPorts() {
1000 if (IsFlagSet(PORTALLOCATOR_DISABLE_RELAY)) {
1001 LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
1002 return;
1003 }
1004
1005 // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
1006 // ought to have a relay list for them here.
1007 ASSERT(config_ && !config_->relays.empty());
1008 if (!(config_ && !config_->relays.empty())) {
1009 LOG(LS_WARNING)
1010 << "AllocationSequence: No relay server configured, skipping.";
1011 return;
1012 }
1013
1014 PortConfiguration::RelayList::const_iterator relay;
1015 for (relay = config_->relays.begin();
1016 relay != config_->relays.end(); ++relay) {
1017 if (relay->type == RELAY_GTURN) {
1018 CreateGturnPort(*relay);
1019 } else if (relay->type == RELAY_TURN) {
1020 CreateTurnPort(*relay);
1021 } else {
1022 ASSERT(false);
1023 }
1024 }
1025}
1026
1027void AllocationSequence::CreateGturnPort(const RelayServerConfig& config) {
1028 // TODO(mallinath) - Rename RelayPort to GTurnPort.
1029 RelayPort* port = RelayPort::Create(session_->network_thread(),
1030 session_->socket_factory(),
1031 network_, ip_,
1032 session_->allocator()->min_port(),
1033 session_->allocator()->max_port(),
1034 config_->username, config_->password);
1035 if (port) {
1036 // Since RelayPort is not created using shared socket, |port| will not be
1037 // added to the dequeue.
1038 // Note: We must add the allocated port before we add addresses because
1039 // the latter will create candidates that need name and preference
1040 // settings. However, we also can't prepare the address (normally
1041 // done by AddAllocatedPort) until we have these addresses. So we
1042 // wait to do that until below.
1043 session_->AddAllocatedPort(port, this, false);
1044
1045 // Add the addresses of this protocol.
1046 PortList::const_iterator relay_port;
1047 for (relay_port = config.ports.begin();
1048 relay_port != config.ports.end();
1049 ++relay_port) {
1050 port->AddServerAddress(*relay_port);
1051 port->AddExternalAddress(*relay_port);
1052 }
1053 // Start fetching an address for this port.
1054 port->PrepareAddress();
1055 }
1056}
1057
1058void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
1059 PortList::const_iterator relay_port;
1060 for (relay_port = config.ports.begin();
1061 relay_port != config.ports.end(); ++relay_port) {
1062 TurnPort* port = NULL;
1063 // Shared socket mode must be enabled only for UDP based ports. Hence
1064 // don't pass shared socket for ports which will create TCP sockets.
1065 // TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
1066 // due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
1067 if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
1068 relay_port->proto == PROTO_UDP) {
1069 port = TurnPort::Create(session_->network_thread(),
1070 session_->socket_factory(),
1071 network_, udp_socket_.get(),
1072 session_->username(), session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001073 *relay_port, config.credentials, config.priority,
1074 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001075 turn_ports_.push_back(port);
1076 // Listen to the port destroyed signal, to allow AllocationSequence to
1077 // remove entrt from it's map.
1078 port->SignalDestroyed.connect(this, &AllocationSequence::OnPortDestroyed);
1079 } else {
1080 port = TurnPort::Create(session_->network_thread(),
1081 session_->socket_factory(),
1082 network_, ip_,
1083 session_->allocator()->min_port(),
1084 session_->allocator()->max_port(),
1085 session_->username(),
1086 session_->password(),
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +00001087 *relay_port, config.credentials, config.priority,
1088 session_->allocator()->origin());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001089 }
1090 ASSERT(port != NULL);
1091 session_->AddAllocatedPort(port, this, true);
1092 }
1093}
1094
1095void AllocationSequence::OnReadPacket(
1096 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
1097 const rtc::SocketAddress& remote_addr,
1098 const rtc::PacketTime& packet_time) {
1099 ASSERT(socket == udp_socket_.get());
1100
1101 bool turn_port_found = false;
1102
1103 // Try to find the TurnPort that matches the remote address. Note that the
1104 // message could be a STUN binding response if the TURN server is also used as
1105 // a STUN server. We don't want to parse every message here to check if it is
1106 // a STUN binding response, so we pass the message to TurnPort regardless of
1107 // the message type. The TurnPort will just ignore the message since it will
1108 // not find any request by transaction ID.
1109 for (std::vector<TurnPort*>::const_iterator it = turn_ports_.begin();
1110 it != turn_ports_.end(); ++it) {
1111 TurnPort* port = *it;
1112 if (port->server_address().address == remote_addr) {
1113 port->HandleIncomingPacket(socket, data, size, remote_addr, packet_time);
1114 turn_port_found = true;
1115 break;
1116 }
1117 }
1118
1119 if (udp_port_) {
1120 const ServerAddresses& stun_servers = udp_port_->server_addresses();
1121
1122 // Pass the packet to the UdpPort if there is no matching TurnPort, or if
1123 // the TURN server is also a STUN server.
1124 if (!turn_port_found ||
1125 stun_servers.find(remote_addr) != stun_servers.end()) {
1126 udp_port_->HandleIncomingPacket(
1127 socket, data, size, remote_addr, packet_time);
1128 }
1129 }
1130}
1131
1132void AllocationSequence::OnPortDestroyed(PortInterface* port) {
1133 if (udp_port_ == port) {
1134 udp_port_ = NULL;
1135 return;
1136 }
1137
jiayl@webrtc.org7e5b3802015-01-22 21:28:39 +00001138 auto it = std::find(turn_ports_.begin(), turn_ports_.end(), port);
1139 if (it != turn_ports_.end()) {
1140 turn_ports_.erase(it);
1141 } else {
1142 LOG(LS_ERROR) << "Unexpected OnPortDestroyed for nonexistent port.";
1143 ASSERT(false);
1144 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001145}
1146
1147// PortConfiguration
1148PortConfiguration::PortConfiguration(
1149 const rtc::SocketAddress& stun_address,
1150 const std::string& username,
1151 const std::string& password)
1152 : stun_address(stun_address), username(username), password(password) {
1153 if (!stun_address.IsNil())
1154 stun_servers.insert(stun_address);
1155}
1156
1157PortConfiguration::PortConfiguration(const ServerAddresses& stun_servers,
1158 const std::string& username,
1159 const std::string& password)
1160 : stun_servers(stun_servers),
1161 username(username),
1162 password(password) {
1163 if (!stun_servers.empty())
1164 stun_address = *(stun_servers.begin());
1165}
1166
1167ServerAddresses PortConfiguration::StunServers() {
1168 if (!stun_address.IsNil() &&
1169 stun_servers.find(stun_address) == stun_servers.end()) {
1170 stun_servers.insert(stun_address);
1171 }
1172 return stun_servers;
1173}
1174
1175void PortConfiguration::AddRelay(const RelayServerConfig& config) {
1176 relays.push_back(config);
1177}
1178
1179bool PortConfiguration::SupportsProtocol(
1180 const RelayServerConfig& relay, ProtocolType type) const {
1181 PortList::const_iterator relay_port;
1182 for (relay_port = relay.ports.begin();
1183 relay_port != relay.ports.end();
1184 ++relay_port) {
1185 if (relay_port->proto == type)
1186 return true;
1187 }
1188 return false;
1189}
1190
1191bool PortConfiguration::SupportsProtocol(RelayType turn_type,
1192 ProtocolType type) const {
1193 for (size_t i = 0; i < relays.size(); ++i) {
1194 if (relays[i].type == turn_type &&
1195 SupportsProtocol(relays[i], type))
1196 return true;
1197 }
1198 return false;
1199}
1200
1201ServerAddresses PortConfiguration::GetRelayServerAddresses(
1202 RelayType turn_type, ProtocolType type) const {
1203 ServerAddresses servers;
1204 for (size_t i = 0; i < relays.size(); ++i) {
1205 if (relays[i].type == turn_type && SupportsProtocol(relays[i], type)) {
1206 servers.insert(relays[i].ports.front().address);
1207 }
1208 }
1209 return servers;
1210}
1211
1212} // namespace cricket