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