• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2012 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 P2P_BASE_TURN_PORT_H_
12 #define P2P_BASE_TURN_PORT_H_
13 
14 #include <stdio.h>
15 
16 #include <map>
17 #include <memory>
18 #include <set>
19 #include <string>
20 #include <vector>
21 
22 #include "absl/memory/memory.h"
23 #include "absl/strings/string_view.h"
24 #include "api/async_dns_resolver.h"
25 #include "api/task_queue/pending_task_safety_flag.h"
26 #include "api/task_queue/task_queue_base.h"
27 #include "p2p/base/port.h"
28 #include "p2p/client/basic_port_allocator.h"
29 #include "rtc_base/async_packet_socket.h"
30 #include "rtc_base/ssl_certificate.h"
31 
32 namespace webrtc {
33 class TurnCustomizer;
34 }
35 
36 namespace cricket {
37 
38 const int kMaxTurnUsernameLength = 509;  // RFC 8489 section 14.3
39 
40 extern const int STUN_ATTR_TURN_LOGGING_ID;
41 extern const char TURN_PORT_TYPE[];
42 class TurnAllocateRequest;
43 class TurnEntry;
44 
45 class TurnPort : public Port {
46  public:
47   enum PortState {
48     STATE_CONNECTING,    // Initial state, cannot send any packets.
49     STATE_CONNECTED,     // Socket connected, ready to send stun requests.
50     STATE_READY,         // Received allocate success, can send any packets.
51     STATE_RECEIVEONLY,   // Had REFRESH_REQUEST error, cannot send any packets.
52     STATE_DISCONNECTED,  // TCP connection died, cannot send/receive any
53                          // packets.
54   };
55 
Validate(const CreateRelayPortArgs & args)56   static bool Validate(const CreateRelayPortArgs& args) {
57     // Do basic parameter validation.
58     if (args.config->credentials.username.size() > kMaxTurnUsernameLength) {
59       RTC_LOG(LS_ERROR) << "Attempt to use TURN with a too long username "
60                         << "of length "
61                         << args.config->credentials.username.size();
62       return false;
63     }
64     // Do not connect to low-numbered ports. The default STUN port is 3478.
65     if (!AllowedTurnPort(args.server_address->address.port(),
66                          args.field_trials)) {
67       RTC_LOG(LS_ERROR) << "Attempt to use TURN to connect to port "
68                         << args.server_address->address.port();
69       return false;
70     }
71     return true;
72   }
73 
74   // Create a TURN port using the shared UDP socket, `socket`.
Create(const CreateRelayPortArgs & args,rtc::AsyncPacketSocket * socket)75   static std::unique_ptr<TurnPort> Create(const CreateRelayPortArgs& args,
76                                           rtc::AsyncPacketSocket* socket) {
77     if (!Validate(args)) {
78       return nullptr;
79     }
80     // Using `new` to access a non-public constructor.
81     return absl::WrapUnique(
82         new TurnPort(args.network_thread, args.socket_factory, args.network,
83                      socket, args.username, args.password, *args.server_address,
84                      args.config->credentials, args.relative_priority,
85                      args.config->tls_alpn_protocols,
86                      args.config->tls_elliptic_curves, args.turn_customizer,
87                      args.config->tls_cert_verifier, args.field_trials));
88   }
89 
90   // Create a TURN port that will use a new socket, bound to `network` and
91   // using a port in the range between `min_port` and `max_port`.
Create(const CreateRelayPortArgs & args,int min_port,int max_port)92   static std::unique_ptr<TurnPort> Create(const CreateRelayPortArgs& args,
93                                           int min_port,
94                                           int max_port) {
95     if (!Validate(args)) {
96       return nullptr;
97     }
98     // Using `new` to access a non-public constructor.
99     return absl::WrapUnique(
100         new TurnPort(args.network_thread, args.socket_factory, args.network,
101                      min_port, max_port, args.username, args.password,
102                      *args.server_address, args.config->credentials,
103                      args.relative_priority, args.config->tls_alpn_protocols,
104                      args.config->tls_elliptic_curves, args.turn_customizer,
105                      args.config->tls_cert_verifier, args.field_trials));
106   }
107 
108   ~TurnPort() override;
109 
server_address()110   const ProtocolAddress& server_address() const { return server_address_; }
111   // Returns an empty address if the local address has not been assigned.
112   rtc::SocketAddress GetLocalAddress() const;
113 
ready()114   bool ready() const { return state_ == STATE_READY; }
connected()115   bool connected() const {
116     return state_ == STATE_READY || state_ == STATE_CONNECTED;
117   }
credentials()118   const RelayCredentials& credentials() const { return credentials_; }
119 
120   ProtocolType GetProtocol() const override;
121 
122   virtual TlsCertPolicy GetTlsCertPolicy() const;
123   virtual void SetTlsCertPolicy(TlsCertPolicy tls_cert_policy);
124 
125   void SetTurnLoggingId(absl::string_view turn_logging_id);
126 
127   virtual std::vector<std::string> GetTlsAlpnProtocols() const;
128   virtual std::vector<std::string> GetTlsEllipticCurves() const;
129 
130   // Release a TURN allocation by sending a refresh with lifetime 0.
131   // Sets state to STATE_RECEIVEONLY.
132   void Release();
133 
134   void PrepareAddress() override;
135   Connection* CreateConnection(const Candidate& c,
136                                PortInterface::CandidateOrigin origin) override;
137   int SendTo(const void* data,
138              size_t size,
139              const rtc::SocketAddress& addr,
140              const rtc::PacketOptions& options,
141              bool payload) override;
142   int SetOption(rtc::Socket::Option opt, int value) override;
143   int GetOption(rtc::Socket::Option opt, int* value) override;
144   int GetError() override;
145 
146   bool HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
147                             const char* data,
148                             size_t size,
149                             const rtc::SocketAddress& remote_addr,
150                             int64_t packet_time_us) override;
151   bool CanHandleIncomingPacketsFrom(
152       const rtc::SocketAddress& addr) const override;
153   virtual void OnReadPacket(rtc::AsyncPacketSocket* socket,
154                             const char* data,
155                             size_t size,
156                             const rtc::SocketAddress& remote_addr,
157                             const int64_t& packet_time_us);
158 
159   void OnSentPacket(rtc::AsyncPacketSocket* socket,
160                     const rtc::SentPacket& sent_packet) override;
161   virtual void OnReadyToSend(rtc::AsyncPacketSocket* socket);
162   bool SupportsProtocol(absl::string_view protocol) const override;
163 
164   void OnSocketConnect(rtc::AsyncPacketSocket* socket);
165   void OnSocketClose(rtc::AsyncPacketSocket* socket, int error);
166 
hash()167   const std::string& hash() const { return hash_; }
nonce()168   const std::string& nonce() const { return nonce_; }
169 
error()170   int error() const { return error_; }
171 
172   void OnAllocateMismatch();
173 
socket()174   rtc::AsyncPacketSocket* socket() const { return socket_; }
request_manager()175   StunRequestManager& request_manager() { return request_manager_; }
176 
HasRequests()177   bool HasRequests() { return !request_manager_.empty(); }
set_credentials(const RelayCredentials & credentials)178   void set_credentials(const RelayCredentials& credentials) {
179     credentials_ = credentials;
180   }
181   // Finds the turn entry with `address` and sets its channel id.
182   // Returns true if the entry is found.
183   bool SetEntryChannelId(const rtc::SocketAddress& address, int channel_id);
184 
185   void HandleConnectionDestroyed(Connection* conn) override;
186 
CloseForTest()187   void CloseForTest() { Close(); }
188 
189   // TODO(solenberg): Tests should be refactored to not peek at internal state.
190   class CallbacksForTest {
191    public:
~CallbacksForTest()192     virtual ~CallbacksForTest() {}
193     virtual void OnTurnCreatePermissionResult(int code) = 0;
194     virtual void OnTurnRefreshResult(int code) = 0;
195     virtual void OnTurnPortClosed() = 0;
196   };
197   void SetCallbacksForTest(CallbacksForTest* callbacks);
198 
199  protected:
200   TurnPort(webrtc::TaskQueueBase* thread,
201            rtc::PacketSocketFactory* factory,
202            const rtc::Network* network,
203            rtc::AsyncPacketSocket* socket,
204            absl::string_view username,
205            absl::string_view password,
206            const ProtocolAddress& server_address,
207            const RelayCredentials& credentials,
208            int server_priority,
209            const std::vector<std::string>& tls_alpn_protocols,
210            const std::vector<std::string>& tls_elliptic_curves,
211            webrtc::TurnCustomizer* customizer,
212            rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr,
213            const webrtc::FieldTrialsView* field_trials = nullptr);
214 
215   TurnPort(webrtc::TaskQueueBase* thread,
216            rtc::PacketSocketFactory* factory,
217            const rtc::Network* network,
218            uint16_t min_port,
219            uint16_t max_port,
220            absl::string_view username,
221            absl::string_view password,
222            const ProtocolAddress& server_address,
223            const RelayCredentials& credentials,
224            int server_priority,
225            const std::vector<std::string>& tls_alpn_protocols,
226            const std::vector<std::string>& tls_elliptic_curves,
227            webrtc::TurnCustomizer* customizer,
228            rtc::SSLCertificateVerifier* tls_cert_verifier = nullptr,
229            const webrtc::FieldTrialsView* field_trials = nullptr);
230 
231   // NOTE: This method needs to be accessible for StunPort
232   // return true if entry was created (i.e channel_number consumed).
233   bool CreateOrRefreshEntry(Connection* conn, int channel_number);
234 
235   rtc::DiffServCodePoint StunDscpValue() const override;
236 
237   // Shuts down the turn port, frees requests and deletes connections.
238   void Close();
239 
240  private:
241   typedef std::map<rtc::Socket::Option, int> SocketOptionsMap;
242   typedef std::set<rtc::SocketAddress> AttemptedServerSet;
243 
244   static bool AllowedTurnPort(int port,
245                               const webrtc::FieldTrialsView* field_trials);
246   void TryAlternateServer();
247 
248   bool CreateTurnClientSocket();
249 
set_nonce(absl::string_view nonce)250   void set_nonce(absl::string_view nonce) { nonce_ = std::string(nonce); }
set_realm(absl::string_view realm)251   void set_realm(absl::string_view realm) {
252     if (realm != realm_) {
253       realm_ = std::string(realm);
254       UpdateHash();
255     }
256   }
257 
258   void OnRefreshError();
259   void HandleRefreshError();
260   bool SetAlternateServer(const rtc::SocketAddress& address);
261   void ResolveTurnAddress(const rtc::SocketAddress& address);
262   void OnResolveResult(rtc::AsyncResolverInterface* resolver);
263 
264   void AddRequestAuthInfo(StunMessage* msg);
265   void OnSendStunPacket(const void* data, size_t size, StunRequest* request);
266   // Stun address from allocate success response.
267   // Currently used only for testing.
268   void OnStunAddress(const rtc::SocketAddress& address);
269   void OnAllocateSuccess(const rtc::SocketAddress& address,
270                          const rtc::SocketAddress& stun_address);
271   void OnAllocateError(int error_code, absl::string_view reason);
272   void OnAllocateRequestTimeout();
273 
274   void HandleDataIndication(const char* data,
275                             size_t size,
276                             int64_t packet_time_us);
277   void HandleChannelData(int channel_id,
278                          const char* data,
279                          size_t size,
280                          int64_t packet_time_us);
281   void DispatchPacket(const char* data,
282                       size_t size,
283                       const rtc::SocketAddress& remote_addr,
284                       ProtocolType proto,
285                       int64_t packet_time_us);
286 
287   bool ScheduleRefresh(uint32_t lifetime);
288   void SendRequest(StunRequest* request, int delay);
289   int Send(const void* data, size_t size, const rtc::PacketOptions& options);
290   void UpdateHash();
291   bool UpdateNonce(StunMessage* response);
292   void ResetNonce();
293 
294   bool HasPermission(const rtc::IPAddress& ipaddr) const;
295   TurnEntry* FindEntry(const rtc::SocketAddress& address) const;
296   TurnEntry* FindEntry(int channel_id) const;
297 
298   // Marks the connection with remote address `address` failed and
299   // pruned (a.k.a. write-timed-out). Returns true if a connection is found.
300   bool FailAndPruneConnection(const rtc::SocketAddress& address);
301 
302   // Reconstruct the URL of the server which the candidate is gathered from.
303   std::string ReconstructedServerUrl();
304 
305   void MaybeAddTurnLoggingId(StunMessage* message);
306 
307   void TurnCustomizerMaybeModifyOutgoingStunMessage(StunMessage* message);
308   bool TurnCustomizerAllowChannelData(const void* data,
309                                       size_t size,
310                                       bool payload);
311 
312   ProtocolAddress server_address_;
313   TlsCertPolicy tls_cert_policy_ = TlsCertPolicy::TLS_CERT_POLICY_SECURE;
314   std::vector<std::string> tls_alpn_protocols_;
315   std::vector<std::string> tls_elliptic_curves_;
316   rtc::SSLCertificateVerifier* tls_cert_verifier_;
317   RelayCredentials credentials_;
318   AttemptedServerSet attempted_server_addresses_;
319 
320   rtc::AsyncPacketSocket* socket_;
321   SocketOptionsMap socket_options_;
322   std::unique_ptr<webrtc::AsyncDnsResolverInterface> resolver_;
323   int error_;
324   rtc::DiffServCodePoint stun_dscp_value_;
325 
326   StunRequestManager request_manager_;
327   std::string realm_;  // From 401/438 response message.
328   std::string nonce_;  // From 401/438 response message.
329   std::string hash_;   // Digest of username:realm:password
330 
331   int next_channel_number_;
332   std::vector<std::unique_ptr<TurnEntry>> entries_;
333 
334   PortState state_;
335   // By default the value will be set to 0. This value will be used in
336   // calculating the candidate priority.
337   int server_priority_;
338 
339   // The number of retries made due to allocate mismatch error.
340   size_t allocate_mismatch_retries_;
341 
342   // Optional TurnCustomizer that can modify outgoing messages. Once set, this
343   // must outlive the TurnPort's lifetime.
344   webrtc::TurnCustomizer* turn_customizer_ = nullptr;
345 
346   // Optional TurnLoggingId.
347   // An identifier set by application that is added to TURN_ALLOCATE_REQUEST
348   // and can be used to match client/backend logs.
349   // TODO(jonaso): This should really be initialized in constructor,
350   // but that is currently so terrible. Fix once constructor is changed
351   // to be more easy to work with.
352   std::string turn_logging_id_;
353 
354   webrtc::ScopedTaskSafety task_safety_;
355 
356   CallbacksForTest* callbacks_for_test_ = nullptr;
357 
358   friend class TurnEntry;
359   friend class TurnAllocateRequest;
360   friend class TurnRefreshRequest;
361   friend class TurnCreatePermissionRequest;
362   friend class TurnChannelBindRequest;
363 };
364 
365 }  // namespace cricket
366 
367 #endif  // P2P_BASE_TURN_PORT_H_
368