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