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