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