blob: 8fbc0d52fa46459bb90433626085373dbe9329cd [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_BASE_STUNPORT_H_
12#define WEBRTC_P2P_BASE_STUNPORT_H_
13
kwiberg3ec46792016-04-27 07:22:53 -070014#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000015#include <string>
16
17#include "webrtc/p2p/base/port.h"
18#include "webrtc/p2p/base/stunrequest.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/rtc_base/asyncpacketsocket.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000020
21// TODO(mallinath) - Rename stunport.cc|h to udpport.cc|h.
22namespace rtc {
23class AsyncResolver;
24class SignalThread;
25}
26
27namespace cricket {
28
Honghai Zhang351d77b2016-05-20 15:08:29 -070029// Lifetime chosen for STUN ports on low-cost networks.
30static const int INFINITE_LIFETIME = -1;
31// Lifetime for STUN ports on high-cost networks: 2 minutes
32static const int HIGH_COST_PORT_KEEPALIVE_LIFETIME = 2 * 60 * 1000;
33
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000034// Communicates using the address on the outside of a NAT.
35class UDPPort : public Port {
36 public:
37 static UDPPort* Create(rtc::Thread* thread,
38 rtc::PacketSocketFactory* factory,
39 rtc::Network* network,
40 rtc::AsyncPacketSocket* socket,
41 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000042 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -070043 const std::string& origin,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -080044 bool emit_local_for_anyaddress) {
45 UDPPort* port = new UDPPort(thread, factory, network, socket, username,
46 password, origin, emit_local_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000047 if (!port->Init()) {
48 delete port;
49 port = NULL;
50 }
51 return port;
52 }
53
54 static UDPPort* Create(rtc::Thread* thread,
55 rtc::PacketSocketFactory* factory,
56 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +020057 uint16_t min_port,
58 uint16_t max_port,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000059 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000060 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -070061 const std::string& origin,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -080062 bool emit_local_for_anyaddress) {
63 UDPPort* port =
deadbeef5c3c1042017-08-04 15:01:57 -070064 new UDPPort(thread, factory, network, min_port, max_port, username,
Guo-wei Shieh9af97f82015-11-10 14:47:39 -080065 password, origin, emit_local_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000066 if (!port->Init()) {
67 delete port;
68 port = NULL;
69 }
70 return port;
71 }
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +000072
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000073 virtual ~UDPPort();
74
75 rtc::SocketAddress GetLocalAddress() const {
76 return socket_->GetLocalAddress();
77 }
78
79 const ServerAddresses& server_addresses() const {
80 return server_addresses_;
81 }
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -070082 void set_server_addresses(const ServerAddresses& addresses) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083 server_addresses_ = addresses;
84 }
85
86 virtual void PrepareAddress();
87
88 virtual Connection* CreateConnection(const Candidate& address,
89 CandidateOrigin origin);
90 virtual int SetOption(rtc::Socket::Option opt, int value);
91 virtual int GetOption(rtc::Socket::Option opt, int* value);
92 virtual int GetError();
93
94 virtual bool HandleIncomingPacket(
95 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
96 const rtc::SocketAddress& remote_addr,
97 const rtc::PacketTime& packet_time) {
98 // All packets given to UDP port will be consumed.
99 OnReadPacket(socket, data, size, remote_addr, packet_time);
100 return true;
101 }
Honghai Zhangf9945b22015-12-15 12:20:13 -0800102 virtual bool SupportsProtocol(const std::string& protocol) const {
103 return protocol == UDP_PROTOCOL_NAME;
104 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000105
Honghai Zhangb9e7b4a2016-06-30 20:52:02 -0700106 virtual ProtocolType GetProtocol() const { return PROTO_UDP; }
107
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000108 void set_stun_keepalive_delay(int delay) {
109 stun_keepalive_delay_ = delay;
110 }
111 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
147 virtual int SendTo(const void* data, size_t size,
148 const rtc::SocketAddress& addr,
149 const rtc::PacketOptions& options,
150 bool payload);
151
Honghai Zhang351d77b2016-05-20 15:08:29 -0700152 virtual void UpdateNetworkCost();
153
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000154 void OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
155 const rtc::SocketAddress& address);
156 void OnReadPacket(rtc::AsyncPacketSocket* socket,
157 const char* data, size_t size,
158 const rtc::SocketAddress& remote_addr,
159 const rtc::PacketTime& packet_time);
160
stefanc1aeaf02015-10-15 07:26:07 -0700161 void OnSentPacket(rtc::AsyncPacketSocket* socket,
162 const rtc::SentPacket& sent_packet);
163
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000164 void OnReadyToSend(rtc::AsyncPacketSocket* socket);
165
166 // This method will send STUN binding request if STUN server address is set.
167 void MaybePrepareStunCandidate();
168
169 void SendStunBindingRequests();
170
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800171 // Helper function which will set |addr|'s IP to the default local address if
Guo-wei Shiehe03cab92015-11-11 11:11:19 -0800172 // |addr| is the "any" address and |emit_local_for_anyaddress_| is true. When
173 // returning false, it indicates that the operation has failed and the
174 // address shouldn't be used by any candidate.
175 bool MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const;
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800176
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000177 private:
178 // A helper class which can be called repeatedly to resolve multiple
179 // addresses, as opposed to rtc::AsyncResolverInterface, which can only
180 // resolve one address per instance.
181 class AddressResolver : public sigslot::has_slots<> {
182 public:
183 explicit AddressResolver(rtc::PacketSocketFactory* factory);
184 ~AddressResolver();
185
186 void Resolve(const rtc::SocketAddress& address);
187 bool GetResolvedAddress(const rtc::SocketAddress& input,
188 int family,
189 rtc::SocketAddress* output) const;
190
191 // The signal is sent when resolving the specified address is finished. The
192 // first argument is the input address, the second argument is the error
193 // or 0 if it succeeded.
194 sigslot::signal2<const rtc::SocketAddress&, int> SignalDone;
195
196 private:
197 typedef std::map<rtc::SocketAddress,
198 rtc::AsyncResolverInterface*> ResolverMap;
199
200 void OnResolveResult(rtc::AsyncResolverInterface* resolver);
201
202 rtc::PacketSocketFactory* socket_factory_;
203 ResolverMap resolvers_;
204 };
205
206 // DNS resolution of the STUN server.
207 void ResolveStunAddress(const rtc::SocketAddress& stun_addr);
208 void OnResolveResult(const rtc::SocketAddress& input, int error);
209
210 void SendStunBindingRequest(const rtc::SocketAddress& stun_addr);
211
212 // Below methods handles binding request responses.
213 void OnStunBindingRequestSucceeded(
214 const rtc::SocketAddress& stun_server_addr,
215 const rtc::SocketAddress& stun_reflected_addr);
216 void OnStunBindingOrResolveRequestFailed(
217 const rtc::SocketAddress& stun_server_addr);
218
219 // Sends STUN requests to the server.
220 void OnSendPacket(const void* data, size_t size, StunRequest* req);
221
222 // TODO(mallinaht) - Move this up to cricket::Port when SignalAddressReady is
223 // changed to SignalPortReady.
224 void MaybeSetPortCompleteOrError();
225
226 bool HasCandidateWithAddress(const rtc::SocketAddress& addr) const;
227
Honghai Zhang351d77b2016-05-20 15:08:29 -0700228 // If this is a low-cost network, it will keep on sending STUN binding
229 // requests indefinitely to keep the NAT binding alive. Otherwise, stop
230 // sending STUN binding requests after HIGH_COST_PORT_KEEPALIVE_LIFETIME.
231 int GetStunKeepaliveLifetime() {
232 return (network_cost() >= rtc::kNetworkCostHigh)
233 ? HIGH_COST_PORT_KEEPALIVE_LIFETIME
234 : INFINITE_LIFETIME;
235 }
236
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000237 ServerAddresses server_addresses_;
238 ServerAddresses bind_request_succeeded_servers_;
239 ServerAddresses bind_request_failed_servers_;
240 StunRequestManager requests_;
241 rtc::AsyncPacketSocket* socket_;
242 int error_;
kwiberg3ec46792016-04-27 07:22:53 -0700243 std::unique_ptr<AddressResolver> resolver_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000244 bool ready_;
245 int stun_keepalive_delay_;
Honghai Zhang351d77b2016-05-20 15:08:29 -0700246 int stun_keepalive_lifetime_ = INFINITE_LIFETIME;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000247
Guo-wei Shieh9af97f82015-11-10 14:47:39 -0800248 // This is true by default and false when
249 // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified.
250 bool emit_local_for_anyaddress_;
Guo-wei Shiehfe3bc9d2015-08-20 08:48:20 -0700251
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000252 friend class StunBindingRequest;
253};
254
255class StunPort : public UDPPort {
256 public:
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000257 static StunPort* Create(rtc::Thread* thread,
258 rtc::PacketSocketFactory* factory,
259 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200260 uint16_t min_port,
261 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000262 const std::string& username,
263 const std::string& password,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000264 const ServerAddresses& servers,
265 const std::string& origin) {
deadbeef5c3c1042017-08-04 15:01:57 -0700266 StunPort* port = new StunPort(thread, factory, network, min_port, max_port,
267 username, password, servers, origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000268 if (!port->Init()) {
269 delete port;
270 port = NULL;
271 }
272 return port;
273 }
274
275 virtual ~StunPort() {}
276
277 virtual void PrepareAddress() {
278 SendStunBindingRequests();
279 }
280
281 protected:
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000282 StunPort(rtc::Thread* thread,
283 rtc::PacketSocketFactory* factory,
284 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200285 uint16_t min_port,
286 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22 +0000287 const std::string& username,
288 const std::string& password,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000289 const ServerAddresses& servers,
290 const std::string& origin)
Peter Boström0c4e06b2015-10-07 12:23:21 +0200291 : UDPPort(thread,
292 factory,
293 network,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200294 min_port,
295 max_port,
296 username,
297 password,
298 origin,
299 false) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000300 // UDPPort will set these to local udp, updating these to STUN.
301 set_type(STUN_PORT_TYPE);
302 set_server_addresses(servers);
303 }
304};
305
306} // namespace cricket
307
308#endif // WEBRTC_P2P_BASE_STUNPORT_H_