blob: 9cb479df0e2b3649366fa420f6cde57404c971fc [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef P2P_BASE_STUNPORT_H_
12#define P2P_BASE_STUNPORT_H_
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013
Steve Anton6c38cc72017-11-29 10:25:58 -080014#include <map>
kwiberg3ec46792016-04-27 07:22:53 -070015#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000016#include <string>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "p2p/base/port.h"
19#include "p2p/base/stunrequest.h"
20#include "rtc_base/asyncpacketsocket.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021
22// TODO(mallinath) - Rename stunport.cc|h to udpport.cc|h.
23namespace rtc {
24class AsyncResolver;
25class SignalThread;
26}
27
28namespace cricket {
29
Honghai Zhang351d77b2016-05-20 15:08:29 -070030// Lifetime chosen for STUN ports on low-cost networks.
31static const int INFINITE_LIFETIME = -1;
32// Lifetime for STUN ports on high-cost networks: 2 minutes
33static const int HIGH_COST_PORT_KEEPALIVE_LIFETIME = 2 * 60 * 1000;
34
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000035// Communicates using the address on the outside of a NAT.
36class UDPPort : public Port {
37 public:
38 static UDPPort* Create(rtc::Thread* thread,
39 rtc::PacketSocketFactory* factory,
40 rtc::Network* network,
41 rtc::AsyncPacketSocket* socket,
42 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000043 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -070044 const std::string& origin,
Qingsi Wang4ff54432018-03-01 18:25:20 -080045 bool emit_local_for_anyaddress,
Danil Chapovalov00c71832018-06-15 15:58:38 +020046 absl::optional<int> stun_keepalive_interval) {
Guo-wei Shieh9af97f82015-11-10 14:47:39 -080047 UDPPort* port = new UDPPort(thread, factory, network, socket, username,
48 password, origin, emit_local_for_anyaddress);
Qingsi Wang4ff54432018-03-01 18:25:20 -080049 port->set_stun_keepalive_delay(stun_keepalive_interval);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 if (!port->Init()) {
51 delete port;
52 port = NULL;
53 }
54 return port;
55 }
56
57 static UDPPort* Create(rtc::Thread* thread,
58 rtc::PacketSocketFactory* factory,
59 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +020060 uint16_t min_port,
61 uint16_t max_port,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000062 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000063 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -070064 const std::string& origin,
Qingsi Wang4ff54432018-03-01 18:25:20 -080065 bool emit_local_for_anyaddress,
Danil Chapovalov00c71832018-06-15 15:58:38 +020066 absl::optional<int> stun_keepalive_interval) {
Guo-wei Shieh9af97f82015-11-10 14:47:39 -080067 UDPPort* port =
deadbeef5c3c1042017-08-04 15:01:57 -070068 new UDPPort(thread, factory, network, min_port, max_port, username,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -080069 password, origin, emit_local_for_anyaddress);
Qingsi Wang4ff54432018-03-01 18:25:20 -080070 port->set_stun_keepalive_delay(stun_keepalive_interval);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000071 if (!port->Init()) {
72 delete port;
73 port = NULL;
74 }
75 return port;
76 }
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000077
Steve Anton1cf1b7d2017-10-30 10:00:15 -070078 ~UDPPort() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000079
80 rtc::SocketAddress GetLocalAddress() const {
81 return socket_->GetLocalAddress();
82 }
83
84 const ServerAddresses& server_addresses() const {
85 return server_addresses_;
86 }
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -070087 void set_server_addresses(const ServerAddresses& addresses) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000088 server_addresses_ = addresses;
89 }
90
Steve Anton1cf1b7d2017-10-30 10:00:15 -070091 void PrepareAddress() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000092
Steve Anton1cf1b7d2017-10-30 10:00:15 -070093 Connection* CreateConnection(const Candidate& address,
94 CandidateOrigin origin) override;
95 int SetOption(rtc::Socket::Option opt, int value) override;
96 int GetOption(rtc::Socket::Option opt, int* value) override;
97 int GetError() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000098
Steve Anton1cf1b7d2017-10-30 10:00:15 -070099 bool HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
100 const char* data,
101 size_t size,
102 const rtc::SocketAddress& remote_addr,
103 const rtc::PacketTime& packet_time) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000104
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700105 bool SupportsProtocol(const std::string& protocol) const override;
106 ProtocolType GetProtocol() const override;
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700107
Danil Chapovalov00c71832018-06-15 15:58:38 +0200108 void GetStunStats(absl::optional<StunStats>* stats) override;
Qingsi Wang72a43a12018-02-20 16:03:18 -0800109
Danil Chapovalov00c71832018-06-15 15:58:38 +0200110 void set_stun_keepalive_delay(const absl::optional<int>& delay);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000111 int stun_keepalive_delay() const {
112 return stun_keepalive_delay_;
113 }
114
honghaize2af9ef2016-03-03 08:27:47 -0800115 // Visible for testing.
116 int stun_keepalive_lifetime() const { return stun_keepalive_lifetime_; }
117 void set_stun_keepalive_lifetime(int lifetime) {
118 stun_keepalive_lifetime_ = lifetime;
119 }
120 // Returns true if there is a pending request with type |msg_type|.
121 bool HasPendingRequest(int msg_type) {
122 return requests_.HasRequest(msg_type);
123 }
124
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000125 protected:
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000126 UDPPort(rtc::Thread* thread,
127 rtc::PacketSocketFactory* factory,
128 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200129 uint16_t min_port,
130 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000131 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000132 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700133 const std::string& origin,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800134 bool emit_local_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000135
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000136 UDPPort(rtc::Thread* thread,
137 rtc::PacketSocketFactory* factory,
138 rtc::Network* network,
139 rtc::AsyncPacketSocket* socket,
140 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000141 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700142 const std::string& origin,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800143 bool emit_local_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000144
145 bool Init();
146
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700147 int SendTo(const void* data,
148 size_t size,
149 const rtc::SocketAddress& addr,
150 const rtc::PacketOptions& options,
151 bool payload) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000152
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700153 void UpdateNetworkCost() override;
Honghai Zhang351d77b2016-05-20 15:08:29 -0700154
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000155 void OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
156 const rtc::SocketAddress& address);
157 void OnReadPacket(rtc::AsyncPacketSocket* socket,
158 const char* data, size_t size,
159 const rtc::SocketAddress& remote_addr,
160 const rtc::PacketTime& packet_time);
161
stefanc1aeaf02015-10-15 07:26:07 -0700162 void OnSentPacket(rtc::AsyncPacketSocket* socket,
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700163 const rtc::SentPacket& sent_packet) override;
stefanc1aeaf02015-10-15 07:26:07 -0700164
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000165 void OnReadyToSend(rtc::AsyncPacketSocket* socket);
166
167 // This method will send STUN binding request if STUN server address is set.
168 void MaybePrepareStunCandidate();
169
170 void SendStunBindingRequests();
171
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800172 // Helper function which will set |addr|'s IP to the default local address if
Guo-wei Shiehe03cab92015-11-11 11:11:19 -0800173 // |addr| is the "any" address and |emit_local_for_anyaddress_| is true. When
174 // returning false, it indicates that the operation has failed and the
175 // address shouldn't be used by any candidate.
176 bool MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const;
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800177
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000178 private:
179 // A helper class which can be called repeatedly to resolve multiple
180 // addresses, as opposed to rtc::AsyncResolverInterface, which can only
181 // resolve one address per instance.
182 class AddressResolver : public sigslot::has_slots<> {
183 public:
184 explicit AddressResolver(rtc::PacketSocketFactory* factory);
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700185 ~AddressResolver() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000186
187 void Resolve(const rtc::SocketAddress& address);
188 bool GetResolvedAddress(const rtc::SocketAddress& input,
189 int family,
190 rtc::SocketAddress* output) const;
191
192 // The signal is sent when resolving the specified address is finished. The
193 // first argument is the input address, the second argument is the error
194 // or 0 if it succeeded.
195 sigslot::signal2<const rtc::SocketAddress&, int> SignalDone;
196
197 private:
198 typedef std::map<rtc::SocketAddress,
199 rtc::AsyncResolverInterface*> ResolverMap;
200
201 void OnResolveResult(rtc::AsyncResolverInterface* resolver);
202
203 rtc::PacketSocketFactory* socket_factory_;
204 ResolverMap resolvers_;
205 };
206
207 // DNS resolution of the STUN server.
208 void ResolveStunAddress(const rtc::SocketAddress& stun_addr);
209 void OnResolveResult(const rtc::SocketAddress& input, int error);
210
211 void SendStunBindingRequest(const rtc::SocketAddress& stun_addr);
212
213 // Below methods handles binding request responses.
214 void OnStunBindingRequestSucceeded(
Qingsi Wang72a43a12018-02-20 16:03:18 -0800215 int rtt_ms,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000216 const rtc::SocketAddress& stun_server_addr,
217 const rtc::SocketAddress& stun_reflected_addr);
218 void OnStunBindingOrResolveRequestFailed(
219 const rtc::SocketAddress& stun_server_addr);
220
221 // Sends STUN requests to the server.
222 void OnSendPacket(const void* data, size_t size, StunRequest* req);
223
224 // TODO(mallinaht) - Move this up to cricket::Port when SignalAddressReady is
225 // changed to SignalPortReady.
226 void MaybeSetPortCompleteOrError();
227
228 bool HasCandidateWithAddress(const rtc::SocketAddress& addr) const;
229
Honghai Zhang351d77b2016-05-20 15:08:29 -0700230 // If this is a low-cost network, it will keep on sending STUN binding
231 // requests indefinitely to keep the NAT binding alive. Otherwise, stop
232 // sending STUN binding requests after HIGH_COST_PORT_KEEPALIVE_LIFETIME.
233 int GetStunKeepaliveLifetime() {
234 return (network_cost() >= rtc::kNetworkCostHigh)
235 ? HIGH_COST_PORT_KEEPALIVE_LIFETIME
236 : INFINITE_LIFETIME;
237 }
238
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000239 ServerAddresses server_addresses_;
240 ServerAddresses bind_request_succeeded_servers_;
241 ServerAddresses bind_request_failed_servers_;
242 StunRequestManager requests_;
243 rtc::AsyncPacketSocket* socket_;
244 int error_;
kwiberg3ec46792016-04-27 07:22:53 -0700245 std::unique_ptr<AddressResolver> resolver_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000246 bool ready_;
247 int stun_keepalive_delay_;
Honghai Zhang351d77b2016-05-20 15:08:29 -0700248 int stun_keepalive_lifetime_ = INFINITE_LIFETIME;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000249
Qingsi Wang72a43a12018-02-20 16:03:18 -0800250 StunStats stats_;
251
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800252 // This is true by default and false when
253 // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified.
254 bool emit_local_for_anyaddress_;
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700255
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000256 friend class StunBindingRequest;
257};
258
259class StunPort : public UDPPort {
260 public:
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000261 static StunPort* Create(rtc::Thread* thread,
262 rtc::PacketSocketFactory* factory,
263 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200264 uint16_t min_port,
265 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000266 const std::string& username,
267 const std::string& password,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000268 const ServerAddresses& servers,
Qingsi Wang4ff54432018-03-01 18:25:20 -0800269 const std::string& origin,
Danil Chapovalov00c71832018-06-15 15:58:38 +0200270 absl::optional<int> stun_keepalive_interval);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000271
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700272 void PrepareAddress() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000273
274 protected:
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000275 StunPort(rtc::Thread* thread,
276 rtc::PacketSocketFactory* factory,
277 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200278 uint16_t min_port,
279 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000280 const std::string& username,
281 const std::string& password,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000282 const ServerAddresses& servers,
Steve Anton1cf1b7d2017-10-30 10:00:15 -0700283 const std::string& origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000284};
285
286} // namespace cricket
287
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200288#endif // P2P_BASE_STUNPORT_H_