blob: 5a4999cce21be860cdea9dccc2949993bf6c68fe [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#ifndef WEBRTC_P2P_CLIENT_BASICPORTALLOCATOR_H_
12#define WEBRTC_P2P_CLIENT_BASICPORTALLOCATOR_H_
13
kwiberg3ec46792016-04-27 07:22:53 -070014#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000015#include <string>
16#include <vector>
17
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000018#include "webrtc/p2p/base/portallocator.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/rtc_base/checks.h"
20#include "webrtc/rtc_base/messagequeue.h"
21#include "webrtc/rtc_base/network.h"
22#include "webrtc/rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000023
24namespace cricket {
25
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000026class BasicPortAllocator : public PortAllocator {
27 public:
28 BasicPortAllocator(rtc::NetworkManager* network_manager,
maxmorine9ef9072017-08-29 04:49:00 -070029 rtc::PacketSocketFactory* socket_factory);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000030 explicit BasicPortAllocator(rtc::NetworkManager* network_manager);
31 BasicPortAllocator(rtc::NetworkManager* network_manager,
32 rtc::PacketSocketFactory* socket_factory,
33 const ServerAddresses& stun_servers);
34 BasicPortAllocator(rtc::NetworkManager* network_manager,
35 const ServerAddresses& stun_servers,
36 const rtc::SocketAddress& relay_server_udp,
37 const rtc::SocketAddress& relay_server_tcp,
38 const rtc::SocketAddress& relay_server_ssl);
39 virtual ~BasicPortAllocator();
40
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080041 // Set to kDefaultNetworkIgnoreMask by default.
42 void SetNetworkIgnoreMask(int network_ignore_mask) override {
43 // TODO(phoglund): implement support for other types than loopback.
44 // See https://code.google.com/p/webrtc/issues/detail?id=4288.
45 // Then remove set_network_ignore_list from NetworkManager.
46 network_ignore_mask_ = network_ignore_mask;
47 }
48
49 int network_ignore_mask() const { return network_ignore_mask_; }
50
Honghai Zhang5622c5e2016-07-01 13:59:29 -070051 rtc::NetworkManager* network_manager() const { return network_manager_; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000052
53 // If socket_factory() is set to NULL each PortAllocatorSession
54 // creates its own socket factory.
55 rtc::PacketSocketFactory* socket_factory() { return socket_factory_; }
56
deadbeef653b8e02015-11-11 12:55:10 -080057 PortAllocatorSession* CreateSessionInternal(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000058 const std::string& content_name,
59 int component,
60 const std::string& ice_ufrag,
deadbeef653b8e02015-11-11 12:55:10 -080061 const std::string& ice_pwd) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000062
Taylor Brandstettera1c30352016-05-13 08:15:11 -070063 // Convenience method that adds a TURN server to the configuration.
64 void AddTurnServer(const RelayServerConfig& turn_server);
65
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066 private:
67 void Construct();
68
Honghai Zhangd93f50c2016-10-05 11:47:22 -070069 void OnIceRegathering(PortAllocatorSession* session,
70 IceRegatheringReason reason);
71
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000072 rtc::NetworkManager* network_manager_;
73 rtc::PacketSocketFactory* socket_factory_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000074 bool allow_tcp_listen_;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080075 int network_ignore_mask_ = rtc::kDefaultNetworkIgnoreMask;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000076};
77
78struct PortConfiguration;
79class AllocationSequence;
80
Honghai Zhangd8f6fc42016-07-01 17:31:12 -070081enum class SessionState {
82 GATHERING, // Actively allocating ports and gathering candidates.
83 CLEARED, // Current allocation process has been stopped but may start
84 // new ones.
85 STOPPED // This session has completely stopped, no new allocation
86 // process will be started.
87};
88
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000089class BasicPortAllocatorSession : public PortAllocatorSession,
90 public rtc::MessageHandler {
91 public:
92 BasicPortAllocatorSession(BasicPortAllocator* allocator,
93 const std::string& content_name,
94 int component,
95 const std::string& ice_ufrag,
96 const std::string& ice_pwd);
97 ~BasicPortAllocatorSession();
98
99 virtual BasicPortAllocator* allocator() { return allocator_; }
100 rtc::Thread* network_thread() { return network_thread_; }
101 rtc::PacketSocketFactory* socket_factory() { return socket_factory_; }
102
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700103 void SetCandidateFilter(uint32_t filter) override;
deadbeef653b8e02015-11-11 12:55:10 -0800104 void StartGettingPorts() override;
105 void StopGettingPorts() override;
106 void ClearGettingPorts() override;
Honghai Zhangd8f6fc42016-07-01 17:31:12 -0700107 bool IsGettingPorts() override { return state_ == SessionState::GATHERING; }
108 bool IsCleared() const override { return state_ == SessionState::CLEARED; }
109 bool IsStopped() const override { return state_ == SessionState::STOPPED; }
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700110 // These will all be cricket::Ports.
111 std::vector<PortInterface*> ReadyPorts() const override;
112 std::vector<Candidate> ReadyCandidates() const override;
113 bool CandidatesAllocationDone() const override;
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700114 void RegatherOnFailedNetworks() override;
Steve Anton300bf8e2017-07-14 10:13:10 -0700115 void RegatherOnAllNetworks() override;
Honghai Zhanga74363c2016-07-28 18:06:15 -0700116 void PruneAllPorts() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000117
118 protected:
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700119 void UpdateIceParametersInternal() override;
120
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000121 // Starts the process of getting the port configurations.
122 virtual void GetPortConfigurations();
123
124 // Adds a port configuration that is now ready. Once we have one for each
125 // network (or a timeout occurs), we will start allocating ports.
126 virtual void ConfigReady(PortConfiguration* config);
127
128 // MessageHandler. Can be overriden if message IDs do not conflict.
deadbeef653b8e02015-11-11 12:55:10 -0800129 void OnMessage(rtc::Message* message) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000130
131 private:
132 class PortData {
133 public:
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700134 PortData() {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000135 PortData(Port* port, AllocationSequence* seq)
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700136 : port_(port), sequence_(seq) {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000137
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700138 Port* port() const { return port_; }
139 AllocationSequence* sequence() const { return sequence_; }
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700140 bool has_pairable_candidate() const { return has_pairable_candidate_; }
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700141 bool complete() const { return state_ == STATE_COMPLETE; }
142 bool error() const { return state_ == STATE_ERROR; }
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700143 bool pruned() const { return state_ == STATE_PRUNED; }
144 bool inprogress() const { return state_ == STATE_INPROGRESS; }
145 // Returns true if this port is ready to be used.
146 bool ready() const {
147 return has_pairable_candidate_ && state_ != STATE_ERROR &&
148 state_ != STATE_PRUNED;
149 }
Honghai Zhangc67e0f52016-09-19 16:57:37 -0700150 // Sets the state to "PRUNED" and prunes the Port.
151 void Prune() {
152 state_ = STATE_PRUNED;
153 if (port()) {
154 port()->Prune();
155 }
156 }
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700157 void set_has_pairable_candidate(bool has_pairable_candidate) {
158 if (has_pairable_candidate) {
nisseede5da42017-01-12 05:15:36 -0800159 RTC_DCHECK(state_ == STATE_INPROGRESS);
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700160 }
161 has_pairable_candidate_ = has_pairable_candidate;
162 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000163 void set_complete() {
164 state_ = STATE_COMPLETE;
165 }
166 void set_error() {
nisseede5da42017-01-12 05:15:36 -0800167 RTC_DCHECK(state_ == STATE_INPROGRESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000168 state_ = STATE_ERROR;
169 }
170
171 private:
172 enum State {
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700173 STATE_INPROGRESS, // Still gathering candidates.
174 STATE_COMPLETE, // All candidates allocated and ready for process.
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700175 STATE_ERROR, // Error in gathering candidates.
176 STATE_PRUNED // Pruned by higher priority ports on the same network
177 // interface. Only TURN ports may be pruned.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000178 };
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700179 Port* port_ = nullptr;
180 AllocationSequence* sequence_ = nullptr;
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700181 bool has_pairable_candidate_ = false;
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700182 State state_ = STATE_INPROGRESS;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000183 };
184
185 void OnConfigReady(PortConfiguration* config);
186 void OnConfigStop();
187 void AllocatePorts();
188 void OnAllocate();
Steve Anton300bf8e2017-07-14 10:13:10 -0700189 void DoAllocate(bool disable_equivalent_phases);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000190 void OnNetworksChanged();
191 void OnAllocationSequenceObjectsCreated();
192 void DisableEquivalentPhases(rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200193 PortConfiguration* config,
194 uint32_t* flags);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000195 void AddAllocatedPort(Port* port, AllocationSequence* seq,
196 bool prepare_address);
197 void OnCandidateReady(Port* port, const Candidate& c);
198 void OnPortComplete(Port* port);
199 void OnPortError(Port* port);
200 void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto);
201 void OnPortDestroyed(PortInterface* port);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000202 void MaybeSignalCandidatesAllocationDone();
203 void OnPortAllocationComplete(AllocationSequence* seq);
204 PortData* FindPort(Port* port);
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700205 std::vector<rtc::Network*> GetNetworks();
206 std::vector<rtc::Network*> GetFailedNetworks();
Steve Anton300bf8e2017-07-14 10:13:10 -0700207 void Regather(const std::vector<rtc::Network*>& networks,
208 bool disable_equivalent_phases,
209 IceRegatheringReason reason);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000210
Taylor Brandstettera1c30352016-05-13 08:15:11 -0700211 bool CheckCandidateFilter(const Candidate& c) const;
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700212 bool CandidatePairable(const Candidate& c, const Port* port) const;
213 // Clear the related address according to the flags and candidate filter
214 // in order to avoid leaking any information.
215 Candidate SanitizeRelatedAddress(const Candidate& c) const;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000216
Honghai Zhangc67e0f52016-09-19 16:57:37 -0700217 std::vector<PortData*> GetUnprunedPorts(
218 const std::vector<rtc::Network*>& networks);
219 // Prunes ports and signal the remote side to remove the candidates that
220 // were previously signaled from these ports.
221 void PrunePortsAndRemoveCandidates(
222 const std::vector<PortData*>& port_data_list);
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700223 // Gets filtered and sanitized candidates generated from a port and
224 // append to |candidates|.
225 void GetCandidatesFromPort(const PortData& data,
226 std::vector<Candidate>* candidates) const;
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700227 Port* GetBestTurnPortForNetwork(const std::string& network_name) const;
228 // Returns true if at least one TURN port is pruned.
229 bool PruneTurnPorts(Port* newly_pairable_turn_port);
230
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000231 BasicPortAllocator* allocator_;
232 rtc::Thread* network_thread_;
kwiberg3ec46792016-04-27 07:22:53 -0700233 std::unique_ptr<rtc::PacketSocketFactory> owned_socket_factory_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000234 rtc::PacketSocketFactory* socket_factory_;
235 bool allocation_started_;
236 bool network_manager_started_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000237 bool allocation_sequences_created_;
238 std::vector<PortConfiguration*> configs_;
239 std::vector<AllocationSequence*> sequences_;
240 std::vector<PortData> ports_;
Taylor Brandstetter417eebe2016-05-23 16:02:19 -0700241 uint32_t candidate_filter_ = CF_ALL;
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700242 // Whether to prune low-priority ports, taken from the port allocator.
243 bool prune_turn_ports_;
Honghai Zhangd8f6fc42016-07-01 17:31:12 -0700244 SessionState state_ = SessionState::CLEARED;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000245
246 friend class AllocationSequence;
247};
248
249// Records configuration information useful in creating ports.
deadbeef653b8e02015-11-11 12:55:10 -0800250// TODO(deadbeef): Rename "relay" to "turn_server" in this struct.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000251struct PortConfiguration : public rtc::MessageData {
252 // TODO(jiayl): remove |stun_address| when Chrome is updated.
253 rtc::SocketAddress stun_address;
254 ServerAddresses stun_servers;
255 std::string username;
256 std::string password;
257
258 typedef std::vector<RelayServerConfig> RelayList;
259 RelayList relays;
260
261 // TODO(jiayl): remove this ctor when Chrome is updated.
262 PortConfiguration(const rtc::SocketAddress& stun_address,
263 const std::string& username,
264 const std::string& password);
265
266 PortConfiguration(const ServerAddresses& stun_servers,
267 const std::string& username,
268 const std::string& password);
269
deadbeefc5d0d952015-07-16 10:22:21 -0700270 // Returns addresses of both the explicitly configured STUN servers,
271 // and TURN servers that should be used as STUN servers.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000272 ServerAddresses StunServers();
273
274 // Adds another relay server, with the given ports and modifier, to the list.
275 void AddRelay(const RelayServerConfig& config);
276
277 // Determines whether the given relay server supports the given protocol.
278 bool SupportsProtocol(const RelayServerConfig& relay,
279 ProtocolType type) const;
280 bool SupportsProtocol(RelayType turn_type, ProtocolType type) const;
281 // Helper method returns the server addresses for the matching RelayType and
282 // Protocol type.
283 ServerAddresses GetRelayServerAddresses(
284 RelayType turn_type, ProtocolType type) const;
285};
286
honghaizf421bdc2015-07-17 16:21:55 -0700287class UDPPort;
288class TurnPort;
289
290// Performs the allocation of ports, in a sequenced (timed) manner, for a given
291// network and IP address.
292class AllocationSequence : public rtc::MessageHandler,
293 public sigslot::has_slots<> {
294 public:
295 enum State {
296 kInit, // Initial state.
297 kRunning, // Started allocating ports.
298 kStopped, // Stopped from running.
299 kCompleted, // All ports are allocated.
300
301 // kInit --> kRunning --> {kCompleted|kStopped}
302 };
303 AllocationSequence(BasicPortAllocatorSession* session,
304 rtc::Network* network,
305 PortConfiguration* config,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200306 uint32_t flags);
honghaizf421bdc2015-07-17 16:21:55 -0700307 ~AllocationSequence();
Honghai Zhang5048f572016-08-23 15:47:33 -0700308 void Init();
honghaizf421bdc2015-07-17 16:21:55 -0700309 void Clear();
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700310 void OnNetworkFailed();
honghaizf421bdc2015-07-17 16:21:55 -0700311
312 State state() const { return state_; }
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700313 rtc::Network* network() const { return network_; }
314
315 bool network_failed() const { return network_failed_; }
316 void set_network_failed() { network_failed_ = true; }
honghaizf421bdc2015-07-17 16:21:55 -0700317
318 // Disables the phases for a new sequence that this one already covers for an
319 // equivalent network setup.
320 void DisableEquivalentPhases(rtc::Network* network,
321 PortConfiguration* config,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200322 uint32_t* flags);
honghaizf421bdc2015-07-17 16:21:55 -0700323
324 // Starts and stops the sequence. When started, it will continue allocating
325 // new ports on its own timed schedule.
326 void Start();
327 void Stop();
328
329 // MessageHandler
330 void OnMessage(rtc::Message* msg);
331
332 void EnableProtocol(ProtocolType proto);
333 bool ProtocolEnabled(ProtocolType proto) const;
334
335 // Signal from AllocationSequence, when it's done with allocating ports.
336 // This signal is useful, when port allocation fails which doesn't result
337 // in any candidates. Using this signal BasicPortAllocatorSession can send
338 // its candidate discovery conclusion signal. Without this signal,
339 // BasicPortAllocatorSession doesn't have any event to trigger signal. This
340 // can also be achieved by starting timer in BPAS.
341 sigslot::signal1<AllocationSequence*> SignalPortAllocationComplete;
342
343 protected:
344 // For testing.
345 void CreateTurnPort(const RelayServerConfig& config);
346
347 private:
348 typedef std::vector<ProtocolType> ProtocolList;
349
Peter Boström0c4e06b2015-10-07 12:23:21 +0200350 bool IsFlagSet(uint32_t flag) { return ((flags_ & flag) != 0); }
honghaizf421bdc2015-07-17 16:21:55 -0700351 void CreateUDPPorts();
352 void CreateTCPPorts();
353 void CreateStunPorts();
354 void CreateRelayPorts();
355 void CreateGturnPort(const RelayServerConfig& config);
356
357 void OnReadPacket(rtc::AsyncPacketSocket* socket,
358 const char* data,
359 size_t size,
360 const rtc::SocketAddress& remote_addr,
361 const rtc::PacketTime& packet_time);
362
363 void OnPortDestroyed(PortInterface* port);
364
365 BasicPortAllocatorSession* session_;
Honghai Zhang5622c5e2016-07-01 13:59:29 -0700366 bool network_failed_ = false;
honghaizf421bdc2015-07-17 16:21:55 -0700367 rtc::Network* network_;
deadbeef5c3c1042017-08-04 15:01:57 -0700368 // Compared with the new best IP in DisableEquivalentPhases.
369 rtc::IPAddress previous_best_ip_;
honghaizf421bdc2015-07-17 16:21:55 -0700370 PortConfiguration* config_;
371 State state_;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200372 uint32_t flags_;
honghaizf421bdc2015-07-17 16:21:55 -0700373 ProtocolList protocols_;
kwiberg3ec46792016-04-27 07:22:53 -0700374 std::unique_ptr<rtc::AsyncPacketSocket> udp_socket_;
honghaizf421bdc2015-07-17 16:21:55 -0700375 // There will be only one udp port per AllocationSequence.
376 UDPPort* udp_port_;
377 std::vector<TurnPort*> turn_ports_;
378 int phase_;
379};
380
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000381} // namespace cricket
382
383#endif // WEBRTC_P2P_CLIENT_BASICPORTALLOCATOR_H_