blob: aa57d666b9d05044369bf42984ab9f7858e06959 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:111/*
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
Steve Anton10542f22019-01-11 17:11:0011#ifndef P2P_BASE_STUN_PORT_H_
12#define P2P_BASE_STUN_PORT_H_
henrike@webrtc.org269fb4b2014-10-28 22:20:1113
Steve Anton6c38cc72017-11-29 18:25:5814#include <map>
kwiberg3ec46792016-04-27 14:22:5315#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:1116#include <string>
17
tzikf0e926f2018-10-15 04:52:1018#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "p2p/base/port.h"
Steve Anton10542f22019-01-11 17:11:0020#include "p2p/base/stun_request.h"
21#include "rtc_base/async_packet_socket.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:1122
23// TODO(mallinath) - Rename stunport.cc|h to udpport.cc|h.
henrike@webrtc.org269fb4b2014-10-28 22:20:1124
25namespace cricket {
26
Honghai Zhang351d77b2016-05-20 22:08:2927// Lifetime chosen for STUN ports on low-cost networks.
28static const int INFINITE_LIFETIME = -1;
29// Lifetime for STUN ports on high-cost networks: 2 minutes
30static const int HIGH_COST_PORT_KEEPALIVE_LIFETIME = 2 * 60 * 1000;
31
henrike@webrtc.org269fb4b2014-10-28 22:20:1132// Communicates using the address on the outside of a NAT.
33class UDPPort : public Port {
34 public:
Steve Antona8f1e562018-10-10 18:29:4435 static std::unique_ptr<UDPPort> Create(
36 rtc::Thread* thread,
37 rtc::PacketSocketFactory* factory,
38 rtc::Network* network,
39 rtc::AsyncPacketSocket* socket,
40 const std::string& username,
41 const std::string& password,
42 const std::string& origin,
43 bool emit_local_for_anyaddress,
44 absl::optional<int> stun_keepalive_interval) {
45 // Using `new` to access a non-public constructor.
46 auto port = absl::WrapUnique(new UDPPort(thread, factory, network, socket,
47 username, password, origin,
48 emit_local_for_anyaddress));
Qingsi Wang4ff54432018-03-02 02:25:2049 port->set_stun_keepalive_delay(stun_keepalive_interval);
henrike@webrtc.org269fb4b2014-10-28 22:20:1150 if (!port->Init()) {
Steve Antona8f1e562018-10-10 18:29:4451 return nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:1152 }
53 return port;
54 }
55
Steve Antona8f1e562018-10-10 18:29:4456 static std::unique_ptr<UDPPort> Create(
57 rtc::Thread* thread,
58 rtc::PacketSocketFactory* factory,
59 rtc::Network* network,
60 uint16_t min_port,
61 uint16_t max_port,
62 const std::string& username,
63 const std::string& password,
64 const std::string& origin,
65 bool emit_local_for_anyaddress,
66 absl::optional<int> stun_keepalive_interval) {
67 // Using `new` to access a non-public constructor.
68 auto port = absl::WrapUnique(
deadbeef5c3c1042017-08-04 22:01:5769 new UDPPort(thread, factory, network, min_port, max_port, username,
Steve Antona8f1e562018-10-10 18:29:4470 password, origin, emit_local_for_anyaddress));
Qingsi Wang4ff54432018-03-02 02:25:2071 port->set_stun_keepalive_delay(stun_keepalive_interval);
henrike@webrtc.org269fb4b2014-10-28 22:20:1172 if (!port->Init()) {
Steve Antona8f1e562018-10-10 18:29:4473 return nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:1174 }
75 return port;
76 }
pthatcher@webrtc.org0ba15332015-01-10 00:47:0277
Steve Anton1cf1b7d2017-10-30 17:00:1578 ~UDPPort() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:1179
80 rtc::SocketAddress GetLocalAddress() const {
81 return socket_->GetLocalAddress();
82 }
83
Jonas Olssona4d87372019-07-05 17:08:3384 const ServerAddresses& server_addresses() const { return server_addresses_; }
Honghai Zhangb9e7b4a2016-07-01 03:52:0285 void set_server_addresses(const ServerAddresses& addresses) {
henrike@webrtc.org269fb4b2014-10-28 22:20:1186 server_addresses_ = addresses;
87 }
88
Steve Anton1cf1b7d2017-10-30 17:00:1589 void PrepareAddress() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:1190
Steve Anton1cf1b7d2017-10-30 17:00:1591 Connection* CreateConnection(const Candidate& address,
92 CandidateOrigin origin) override;
93 int SetOption(rtc::Socket::Option opt, int value) override;
94 int GetOption(rtc::Socket::Option opt, int* value) override;
95 int GetError() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:1196
Steve Anton1cf1b7d2017-10-30 17:00:1597 bool HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
98 const char* data,
99 size_t size,
100 const rtc::SocketAddress& remote_addr,
Niels Möllere6933812018-11-05 12:01:41101 int64_t packet_time_us) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11102
Steve Anton1cf1b7d2017-10-30 17:00:15103 bool SupportsProtocol(const std::string& protocol) const override;
104 ProtocolType GetProtocol() const override;
Honghai Zhangb9e7b4a2016-07-01 03:52:02105
Danil Chapovalov00c718362018-06-15 13:58:38106 void GetStunStats(absl::optional<StunStats>* stats) override;
Qingsi Wang72a43a12018-02-21 00:03:18107
Danil Chapovalov00c718362018-06-15 13:58:38108 void set_stun_keepalive_delay(const absl::optional<int>& delay);
Jonas Olssona4d87372019-07-05 17:08:33109 int stun_keepalive_delay() const { return stun_keepalive_delay_; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11110
honghaize2af9ef2016-03-03 16:27:47111 // Visible for testing.
112 int stun_keepalive_lifetime() const { return stun_keepalive_lifetime_; }
113 void set_stun_keepalive_lifetime(int lifetime) {
114 stun_keepalive_lifetime_ = lifetime;
115 }
116 // Returns true if there is a pending request with type |msg_type|.
117 bool HasPendingRequest(int msg_type) {
118 return requests_.HasRequest(msg_type);
119 }
120
henrike@webrtc.org269fb4b2014-10-28 22:20:11121 protected:
pkasting@chromium.org332331f2014-11-06 20:19:22122 UDPPort(rtc::Thread* thread,
123 rtc::PacketSocketFactory* factory,
124 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 10:23:21125 uint16_t min_port,
126 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22127 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02128 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 15:48:20129 const std::string& origin,
Guo-wei Shieh9af97f82015-11-10 22:47:39130 bool emit_local_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11131
pkasting@chromium.org332331f2014-11-06 20:19:22132 UDPPort(rtc::Thread* thread,
133 rtc::PacketSocketFactory* factory,
134 rtc::Network* network,
135 rtc::AsyncPacketSocket* socket,
136 const std::string& username,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02137 const std::string& password,
Guo-wei Shiehfe3bc9d2015-08-20 15:48:20138 const std::string& origin,
Guo-wei Shieh9af97f82015-11-10 22:47:39139 bool emit_local_for_anyaddress);
henrike@webrtc.org269fb4b2014-10-28 22:20:11140
141 bool Init();
142
Steve Anton1cf1b7d2017-10-30 17:00:15143 int SendTo(const void* data,
144 size_t size,
145 const rtc::SocketAddress& addr,
146 const rtc::PacketOptions& options,
147 bool payload) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11148
Steve Anton1cf1b7d2017-10-30 17:00:15149 void UpdateNetworkCost() override;
Honghai Zhang351d77b2016-05-20 22:08:29150
Tim Haloun6ca98362018-09-18 00:06:08151 rtc::DiffServCodePoint StunDscpValue() const override;
152
henrike@webrtc.org269fb4b2014-10-28 22:20:11153 void OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
154 const rtc::SocketAddress& address);
Qingsi Wang3ea7b832018-11-07 01:51:02155
156 void PostAddAddress(bool is_final) override;
157
henrike@webrtc.org269fb4b2014-10-28 22:20:11158 void OnReadPacket(rtc::AsyncPacketSocket* socket,
Niels Möllere6933812018-11-05 12:01:41159 const char* data,
160 size_t size,
henrike@webrtc.org269fb4b2014-10-28 22:20:11161 const rtc::SocketAddress& remote_addr,
Niels Möllere6933812018-11-05 12:01:41162 const int64_t& packet_time_us);
henrike@webrtc.org269fb4b2014-10-28 22:20:11163
stefanc1aeaf02015-10-15 14:26:07164 void OnSentPacket(rtc::AsyncPacketSocket* socket,
Steve Anton1cf1b7d2017-10-30 17:00:15165 const rtc::SentPacket& sent_packet) override;
stefanc1aeaf02015-10-15 14:26:07166
henrike@webrtc.org269fb4b2014-10-28 22:20:11167 void OnReadyToSend(rtc::AsyncPacketSocket* socket);
168
169 // This method will send STUN binding request if STUN server address is set.
170 void MaybePrepareStunCandidate();
171
172 void SendStunBindingRequests();
173
Guo-wei Shieh9af97f82015-11-10 22:47:39174 // Helper function which will set |addr|'s IP to the default local address if
Guo-wei Shiehe03cab92015-11-11 19:11:19175 // |addr| is the "any" address and |emit_local_for_anyaddress_| is true. When
176 // returning false, it indicates that the operation has failed and the
177 // address shouldn't be used by any candidate.
178 bool MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const;
Guo-wei Shieh9af97f82015-11-10 22:47:39179
henrike@webrtc.org269fb4b2014-10-28 22:20:11180 private:
181 // A helper class which can be called repeatedly to resolve multiple
182 // addresses, as opposed to rtc::AsyncResolverInterface, which can only
183 // resolve one address per instance.
184 class AddressResolver : public sigslot::has_slots<> {
185 public:
186 explicit AddressResolver(rtc::PacketSocketFactory* factory);
Steve Anton1cf1b7d2017-10-30 17:00:15187 ~AddressResolver() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11188
189 void Resolve(const rtc::SocketAddress& address);
190 bool GetResolvedAddress(const rtc::SocketAddress& input,
191 int family,
192 rtc::SocketAddress* output) const;
193
194 // The signal is sent when resolving the specified address is finished. The
195 // first argument is the input address, the second argument is the error
196 // or 0 if it succeeded.
197 sigslot::signal2<const rtc::SocketAddress&, int> SignalDone;
198
199 private:
Jonas Olssona4d87372019-07-05 17:08:33200 typedef std::map<rtc::SocketAddress, rtc::AsyncResolverInterface*>
201 ResolverMap;
henrike@webrtc.org269fb4b2014-10-28 22:20:11202
203 void OnResolveResult(rtc::AsyncResolverInterface* resolver);
204
205 rtc::PacketSocketFactory* socket_factory_;
206 ResolverMap resolvers_;
207 };
208
209 // DNS resolution of the STUN server.
210 void ResolveStunAddress(const rtc::SocketAddress& stun_addr);
211 void OnResolveResult(const rtc::SocketAddress& input, int error);
212
213 void SendStunBindingRequest(const rtc::SocketAddress& stun_addr);
214
215 // Below methods handles binding request responses.
216 void OnStunBindingRequestSucceeded(
Qingsi Wang72a43a12018-02-21 00:03:18217 int rtt_ms,
henrike@webrtc.org269fb4b2014-10-28 22:20:11218 const rtc::SocketAddress& stun_server_addr,
219 const rtc::SocketAddress& stun_reflected_addr);
220 void OnStunBindingOrResolveRequestFailed(
Eldar Relloda13ea22019-06-01 09:23:43221 const rtc::SocketAddress& stun_server_addr,
222 int error_code,
223 const std::string& reason);
henrike@webrtc.org269fb4b2014-10-28 22:20:11224
225 // Sends STUN requests to the server.
226 void OnSendPacket(const void* data, size_t size, StunRequest* req);
227
228 // TODO(mallinaht) - Move this up to cricket::Port when SignalAddressReady is
229 // changed to SignalPortReady.
230 void MaybeSetPortCompleteOrError();
231
232 bool HasCandidateWithAddress(const rtc::SocketAddress& addr) const;
233
Honghai Zhang351d77b2016-05-20 22:08:29234 // If this is a low-cost network, it will keep on sending STUN binding
235 // requests indefinitely to keep the NAT binding alive. Otherwise, stop
236 // sending STUN binding requests after HIGH_COST_PORT_KEEPALIVE_LIFETIME.
237 int GetStunKeepaliveLifetime() {
238 return (network_cost() >= rtc::kNetworkCostHigh)
239 ? HIGH_COST_PORT_KEEPALIVE_LIFETIME
240 : INFINITE_LIFETIME;
241 }
242
henrike@webrtc.org269fb4b2014-10-28 22:20:11243 ServerAddresses server_addresses_;
244 ServerAddresses bind_request_succeeded_servers_;
245 ServerAddresses bind_request_failed_servers_;
246 StunRequestManager requests_;
247 rtc::AsyncPacketSocket* socket_;
248 int error_;
Zach Stein4d92b842018-08-23 00:41:35249 int send_error_count_ = 0;
kwiberg3ec46792016-04-27 14:22:53250 std::unique_ptr<AddressResolver> resolver_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11251 bool ready_;
252 int stun_keepalive_delay_;
Honghai Zhang351d77b2016-05-20 22:08:29253 int stun_keepalive_lifetime_ = INFINITE_LIFETIME;
Tim Haloun6ca98362018-09-18 00:06:08254 rtc::DiffServCodePoint dscp_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11255
Qingsi Wang72a43a12018-02-21 00:03:18256 StunStats stats_;
257
Guo-wei Shieh9af97f82015-11-10 22:47:39258 // This is true by default and false when
259 // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified.
260 bool emit_local_for_anyaddress_;
Guo-wei Shiehfe3bc9d2015-08-20 15:48:20261
henrike@webrtc.org269fb4b2014-10-28 22:20:11262 friend class StunBindingRequest;
263};
264
265class StunPort : public UDPPort {
266 public:
Steve Antona8f1e562018-10-10 18:29:44267 static std::unique_ptr<StunPort> Create(
268 rtc::Thread* thread,
269 rtc::PacketSocketFactory* factory,
270 rtc::Network* network,
271 uint16_t min_port,
272 uint16_t max_port,
273 const std::string& username,
274 const std::string& password,
275 const ServerAddresses& servers,
276 const std::string& origin,
277 absl::optional<int> stun_keepalive_interval);
henrike@webrtc.org269fb4b2014-10-28 22:20:11278
Steve Anton1cf1b7d2017-10-30 17:00:15279 void PrepareAddress() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11280
281 protected:
pkasting@chromium.org332331f2014-11-06 20:19:22282 StunPort(rtc::Thread* thread,
283 rtc::PacketSocketFactory* factory,
284 rtc::Network* network,
Peter Boström0c4e06b2015-10-07 10:23:21285 uint16_t min_port,
286 uint16_t max_port,
pkasting@chromium.org332331f2014-11-06 20:19:22287 const std::string& username,
288 const std::string& password,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02289 const ServerAddresses& servers,
Steve Anton1cf1b7d2017-10-30 17:00:15290 const std::string& origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11291};
292
293} // namespace cricket
294
Steve Anton10542f22019-01-11 17:11:00295#endif // P2P_BASE_STUN_PORT_H_