• 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 #include "p2p/base/turn_port.h"
12 
13 #include <functional>
14 #include <memory>
15 #include <utility>
16 #include <vector>
17 
18 #include "absl/algorithm/container.h"
19 #include "absl/strings/match.h"
20 #include "absl/types/optional.h"
21 #include "api/transport/stun.h"
22 #include "p2p/base/connection.h"
23 #include "p2p/base/p2p_constants.h"
24 #include "rtc_base/async_packet_socket.h"
25 #include "rtc_base/byte_order.h"
26 #include "rtc_base/checks.h"
27 #include "rtc_base/logging.h"
28 #include "rtc_base/net_helpers.h"
29 #include "rtc_base/socket_address.h"
30 #include "rtc_base/strings/string_builder.h"
31 #include "system_wrappers/include/field_trial.h"
32 
33 namespace cricket {
34 
35 // TODO(juberti): Move to stun.h when relay messages have been renamed.
36 static const int TURN_ALLOCATE_REQUEST = STUN_ALLOCATE_REQUEST;
37 
38 // Attributes in comprehension-optional range,
39 // ignored by TURN server that doesn't know about them.
40 // https://tools.ietf.org/html/rfc5389#section-18.2
41 static const int STUN_ATTR_MULTI_MAPPING = 0xff04;
42 const int STUN_ATTR_TURN_LOGGING_ID = 0xff05;
43 
44 // TODO(juberti): Extract to turnmessage.h
45 static const int TURN_DEFAULT_PORT = 3478;
46 static const int TURN_CHANNEL_NUMBER_START = 0x4000;
47 static const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000;  // 5 minutes
48 
49 static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
50 
51 // Retry at most twice (i.e. three different ALLOCATE requests) on
52 // STUN_ERROR_ALLOCATION_MISMATCH error per rfc5766.
53 static const size_t MAX_ALLOCATE_MISMATCH_RETRIES = 2;
54 
55 static const int TURN_SUCCESS_RESULT_CODE = 0;
56 
IsTurnChannelData(uint16_t msg_type)57 inline bool IsTurnChannelData(uint16_t msg_type) {
58   return ((msg_type & 0xC000) == 0x4000);  // MSB are 0b01
59 }
60 
GetRelayPreference(cricket::ProtocolType proto)61 static int GetRelayPreference(cricket::ProtocolType proto) {
62   switch (proto) {
63     case cricket::PROTO_TCP:
64       return ICE_TYPE_PREFERENCE_RELAY_TCP;
65     case cricket::PROTO_TLS:
66       return ICE_TYPE_PREFERENCE_RELAY_TLS;
67     default:
68       RTC_DCHECK(proto == PROTO_UDP);
69       return ICE_TYPE_PREFERENCE_RELAY_UDP;
70   }
71 }
72 
73 class TurnAllocateRequest : public StunRequest {
74  public:
75   explicit TurnAllocateRequest(TurnPort* port);
76   void Prepare(StunMessage* request) override;
77   void OnSent() override;
78   void OnResponse(StunMessage* response) override;
79   void OnErrorResponse(StunMessage* response) override;
80   void OnTimeout() override;
81 
82  private:
83   // Handles authentication challenge from the server.
84   void OnAuthChallenge(StunMessage* response, int code);
85   void OnTryAlternate(StunMessage* response, int code);
86   void OnUnknownAttribute(StunMessage* response);
87 
88   TurnPort* port_;
89 };
90 
91 class TurnRefreshRequest : public StunRequest {
92  public:
93   explicit TurnRefreshRequest(TurnPort* port);
94   void Prepare(StunMessage* request) override;
95   void OnSent() override;
96   void OnResponse(StunMessage* response) override;
97   void OnErrorResponse(StunMessage* response) override;
98   void OnTimeout() override;
set_lifetime(int lifetime)99   void set_lifetime(int lifetime) { lifetime_ = lifetime; }
100 
101  private:
102   TurnPort* port_;
103   int lifetime_;
104 };
105 
106 class TurnCreatePermissionRequest : public StunRequest,
107                                     public sigslot::has_slots<> {
108  public:
109   TurnCreatePermissionRequest(TurnPort* port,
110                               TurnEntry* entry,
111                               const rtc::SocketAddress& ext_addr,
112                               const std::string& remote_ufrag);
113   void Prepare(StunMessage* request) override;
114   void OnSent() override;
115   void OnResponse(StunMessage* response) override;
116   void OnErrorResponse(StunMessage* response) override;
117   void OnTimeout() override;
118 
119  private:
120   void OnEntryDestroyed(TurnEntry* entry);
121 
122   TurnPort* port_;
123   TurnEntry* entry_;
124   rtc::SocketAddress ext_addr_;
125   std::string remote_ufrag_;
126 };
127 
128 class TurnChannelBindRequest : public StunRequest, public sigslot::has_slots<> {
129  public:
130   TurnChannelBindRequest(TurnPort* port,
131                          TurnEntry* entry,
132                          int channel_id,
133                          const rtc::SocketAddress& ext_addr);
134   void Prepare(StunMessage* request) override;
135   void OnSent() override;
136   void OnResponse(StunMessage* response) override;
137   void OnErrorResponse(StunMessage* response) override;
138   void OnTimeout() override;
139 
140  private:
141   void OnEntryDestroyed(TurnEntry* entry);
142 
143   TurnPort* port_;
144   TurnEntry* entry_;
145   int channel_id_;
146   rtc::SocketAddress ext_addr_;
147 };
148 
149 // Manages a "connection" to a remote destination. We will attempt to bring up
150 // a channel for this remote destination to reduce the overhead of sending data.
151 class TurnEntry : public sigslot::has_slots<> {
152  public:
153   enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
154   TurnEntry(TurnPort* port,
155             int channel_id,
156             const rtc::SocketAddress& ext_addr,
157             const std::string remote_ufrag);
158 
port()159   TurnPort* port() { return port_; }
160 
channel_id() const161   int channel_id() const { return channel_id_; }
162   // For testing only.
set_channel_id(int channel_id)163   void set_channel_id(int channel_id) { channel_id_ = channel_id; }
164 
address() const165   const rtc::SocketAddress& address() const { return ext_addr_; }
state() const166   BindState state() const { return state_; }
167 
168   // If the destruction timestamp is set, that means destruction has been
169   // scheduled (will occur TURN_PERMISSION_TIMEOUT after it's scheduled).
destruction_timestamp()170   absl::optional<int64_t> destruction_timestamp() {
171     return destruction_timestamp_;
172   }
set_destruction_timestamp(int64_t destruction_timestamp)173   void set_destruction_timestamp(int64_t destruction_timestamp) {
174     destruction_timestamp_.emplace(destruction_timestamp);
175   }
reset_destruction_timestamp()176   void reset_destruction_timestamp() { destruction_timestamp_.reset(); }
177 
178   // Helper methods to send permission and channel bind requests.
179   void SendCreatePermissionRequest(int delay);
180   void SendChannelBindRequest(int delay);
181   // Sends a packet to the given destination address.
182   // This will wrap the packet in STUN if necessary.
183   int Send(const void* data,
184            size_t size,
185            bool payload,
186            const rtc::PacketOptions& options);
187 
188   void OnCreatePermissionSuccess();
189   void OnCreatePermissionError(StunMessage* response, int code);
190   void OnCreatePermissionTimeout();
191   void OnChannelBindSuccess();
192   void OnChannelBindError(StunMessage* response, int code);
193   void OnChannelBindTimeout();
194   // Signal sent when TurnEntry is destroyed.
195   sigslot::signal1<TurnEntry*> SignalDestroyed;
196 
get_remote_ufrag() const197   const std::string& get_remote_ufrag() const { return remote_ufrag_; }
set_remote_ufrag(const std::string & remote_ufrag)198   void set_remote_ufrag(const std::string& remote_ufrag) {
199     remote_ufrag_ = remote_ufrag;
200   }
201 
202  private:
203   TurnPort* port_;
204   int channel_id_;
205   rtc::SocketAddress ext_addr_;
206   BindState state_;
207   // An unset value indicates that this entry is scheduled to be destroyed. It
208   // is also used as an ID of the event scheduling. When the destruction event
209   // actually fires, the TurnEntry will be destroyed only if the timestamp here
210   // matches the one in the firing event.
211   absl::optional<int64_t> destruction_timestamp_;
212 
213   std::string remote_ufrag_;
214 };
215 
TurnPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,rtc::AsyncPacketSocket * socket,const std::string & username,const std::string & password,const ProtocolAddress & server_address,const RelayCredentials & credentials,int server_priority,const std::string & origin,webrtc::TurnCustomizer * customizer)216 TurnPort::TurnPort(rtc::Thread* thread,
217                    rtc::PacketSocketFactory* factory,
218                    rtc::Network* network,
219                    rtc::AsyncPacketSocket* socket,
220                    const std::string& username,
221                    const std::string& password,
222                    const ProtocolAddress& server_address,
223                    const RelayCredentials& credentials,
224                    int server_priority,
225                    const std::string& origin,
226                    webrtc::TurnCustomizer* customizer)
227     : Port(thread, RELAY_PORT_TYPE, factory, network, username, password),
228       server_address_(server_address),
229       tls_cert_verifier_(nullptr),
230       credentials_(credentials),
231       socket_(socket),
232       resolver_(NULL),
233       error_(0),
234       stun_dscp_value_(rtc::DSCP_NO_CHANGE),
235       request_manager_(thread),
236       next_channel_number_(TURN_CHANNEL_NUMBER_START),
237       state_(STATE_CONNECTING),
238       server_priority_(server_priority),
239       allocate_mismatch_retries_(0),
240       turn_customizer_(customizer) {
241   request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
242   request_manager_.set_origin(origin);
243 }
244 
TurnPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,uint16_t min_port,uint16_t max_port,const std::string & username,const std::string & password,const ProtocolAddress & server_address,const RelayCredentials & credentials,int server_priority,const std::string & origin,const std::vector<std::string> & tls_alpn_protocols,const std::vector<std::string> & tls_elliptic_curves,webrtc::TurnCustomizer * customizer,rtc::SSLCertificateVerifier * tls_cert_verifier)245 TurnPort::TurnPort(rtc::Thread* thread,
246                    rtc::PacketSocketFactory* factory,
247                    rtc::Network* network,
248                    uint16_t min_port,
249                    uint16_t max_port,
250                    const std::string& username,
251                    const std::string& password,
252                    const ProtocolAddress& server_address,
253                    const RelayCredentials& credentials,
254                    int server_priority,
255                    const std::string& origin,
256                    const std::vector<std::string>& tls_alpn_protocols,
257                    const std::vector<std::string>& tls_elliptic_curves,
258                    webrtc::TurnCustomizer* customizer,
259                    rtc::SSLCertificateVerifier* tls_cert_verifier)
260     : Port(thread,
261            RELAY_PORT_TYPE,
262            factory,
263            network,
264            min_port,
265            max_port,
266            username,
267            password),
268       server_address_(server_address),
269       tls_alpn_protocols_(tls_alpn_protocols),
270       tls_elliptic_curves_(tls_elliptic_curves),
271       tls_cert_verifier_(tls_cert_verifier),
272       credentials_(credentials),
273       socket_(NULL),
274       resolver_(NULL),
275       error_(0),
276       stun_dscp_value_(rtc::DSCP_NO_CHANGE),
277       request_manager_(thread),
278       next_channel_number_(TURN_CHANNEL_NUMBER_START),
279       state_(STATE_CONNECTING),
280       server_priority_(server_priority),
281       allocate_mismatch_retries_(0),
282       turn_customizer_(customizer) {
283   request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
284   request_manager_.set_origin(origin);
285 }
286 
~TurnPort()287 TurnPort::~TurnPort() {
288   // TODO(juberti): Should this even be necessary?
289 
290   // release the allocation by sending a refresh with
291   // lifetime 0.
292   if (ready()) {
293     Release();
294   }
295 
296   while (!entries_.empty()) {
297     DestroyEntry(entries_.front());
298   }
299   if (resolver_) {
300     resolver_->Destroy(false);
301   }
302   if (!SharedSocket()) {
303     delete socket_;
304   }
305 }
306 
GetLocalAddress() const307 rtc::SocketAddress TurnPort::GetLocalAddress() const {
308   return socket_ ? socket_->GetLocalAddress() : rtc::SocketAddress();
309 }
310 
GetProtocol() const311 ProtocolType TurnPort::GetProtocol() const {
312   return server_address_.proto;
313 }
314 
GetTlsCertPolicy() const315 TlsCertPolicy TurnPort::GetTlsCertPolicy() const {
316   return tls_cert_policy_;
317 }
318 
SetTlsCertPolicy(TlsCertPolicy tls_cert_policy)319 void TurnPort::SetTlsCertPolicy(TlsCertPolicy tls_cert_policy) {
320   tls_cert_policy_ = tls_cert_policy;
321 }
322 
SetTurnLoggingId(const std::string & turn_logging_id)323 void TurnPort::SetTurnLoggingId(const std::string& turn_logging_id) {
324   turn_logging_id_ = turn_logging_id;
325 }
326 
GetTlsAlpnProtocols() const327 std::vector<std::string> TurnPort::GetTlsAlpnProtocols() const {
328   return tls_alpn_protocols_;
329 }
330 
GetTlsEllipticCurves() const331 std::vector<std::string> TurnPort::GetTlsEllipticCurves() const {
332   return tls_elliptic_curves_;
333 }
334 
PrepareAddress()335 void TurnPort::PrepareAddress() {
336   if (credentials_.username.empty() || credentials_.password.empty()) {
337     RTC_LOG(LS_ERROR) << "Allocation can't be started without setting the"
338                          " TURN server credentials for the user.";
339     OnAllocateError(STUN_ERROR_UNAUTHORIZED,
340                     "Missing TURN server credentials.");
341     return;
342   }
343 
344   if (!server_address_.address.port()) {
345     // We will set default TURN port, if no port is set in the address.
346     server_address_.address.SetPort(TURN_DEFAULT_PORT);
347   }
348 
349   if (server_address_.address.IsUnresolvedIP()) {
350     ResolveTurnAddress(server_address_.address);
351   } else {
352     // If protocol family of server address doesn't match with local, return.
353     if (!IsCompatibleAddress(server_address_.address)) {
354       RTC_LOG(LS_ERROR) << "IP address family does not match. server: "
355                         << server_address_.address.family()
356                         << " local: " << Network()->GetBestIP().family();
357       OnAllocateError(STUN_ERROR_GLOBAL_FAILURE,
358                       "IP address family does not match.");
359       return;
360     }
361 
362     // Insert the current address to prevent redirection pingpong.
363     attempted_server_addresses_.insert(server_address_.address);
364 
365     RTC_LOG(LS_INFO) << ToString() << ": Trying to connect to TURN server via "
366                      << ProtoToString(server_address_.proto) << " @ "
367                      << server_address_.address.ToSensitiveString();
368     if (!CreateTurnClientSocket()) {
369       RTC_LOG(LS_ERROR) << "Failed to create TURN client socket";
370       OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
371                       "Failed to create TURN client socket.");
372       return;
373     }
374     if (server_address_.proto == PROTO_UDP) {
375       // If its UDP, send AllocateRequest now.
376       // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
377       SendRequest(new TurnAllocateRequest(this), 0);
378     }
379   }
380 }
381 
CreateTurnClientSocket()382 bool TurnPort::CreateTurnClientSocket() {
383   RTC_DCHECK(!socket_ || SharedSocket());
384 
385   if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
386     socket_ = socket_factory()->CreateUdpSocket(
387         rtc::SocketAddress(Network()->GetBestIP(), 0), min_port(), max_port());
388   } else if (server_address_.proto == PROTO_TCP ||
389              server_address_.proto == PROTO_TLS) {
390     RTC_DCHECK(!SharedSocket());
391     int opts = rtc::PacketSocketFactory::OPT_STUN;
392 
393     // Apply server address TLS and insecure bits to options.
394     if (server_address_.proto == PROTO_TLS) {
395       if (tls_cert_policy_ ==
396           TlsCertPolicy::TLS_CERT_POLICY_INSECURE_NO_CHECK) {
397         opts |= rtc::PacketSocketFactory::OPT_TLS_INSECURE;
398       } else {
399         opts |= rtc::PacketSocketFactory::OPT_TLS;
400       }
401     }
402 
403     rtc::PacketSocketTcpOptions tcp_options;
404     tcp_options.opts = opts;
405     tcp_options.tls_alpn_protocols = tls_alpn_protocols_;
406     tcp_options.tls_elliptic_curves = tls_elliptic_curves_;
407     tcp_options.tls_cert_verifier = tls_cert_verifier_;
408     socket_ = socket_factory()->CreateClientTcpSocket(
409         rtc::SocketAddress(Network()->GetBestIP(), 0), server_address_.address,
410         proxy(), user_agent(), tcp_options);
411   }
412 
413   if (!socket_) {
414     error_ = SOCKET_ERROR;
415     return false;
416   }
417 
418   // Apply options if any.
419   for (SocketOptionsMap::iterator iter = socket_options_.begin();
420        iter != socket_options_.end(); ++iter) {
421     socket_->SetOption(iter->first, iter->second);
422   }
423 
424   if (!SharedSocket()) {
425     // If socket is shared, AllocationSequence will receive the packet.
426     socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
427   }
428 
429   socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
430 
431   socket_->SignalSentPacket.connect(this, &TurnPort::OnSentPacket);
432 
433   // TCP port is ready to send stun requests after the socket is connected,
434   // while UDP port is ready to do so once the socket is created.
435   if (server_address_.proto == PROTO_TCP ||
436       server_address_.proto == PROTO_TLS) {
437     socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
438     socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
439   } else {
440     state_ = STATE_CONNECTED;
441   }
442   return true;
443 }
444 
OnSocketConnect(rtc::AsyncPacketSocket * socket)445 void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
446   // This slot should only be invoked if we're using a connection-oriented
447   // protocol.
448   RTC_DCHECK(server_address_.proto == PROTO_TCP ||
449              server_address_.proto == PROTO_TLS);
450 
451   // Do not use this port if the socket bound to an address not associated with
452   // the desired network interface. This is seen in Chrome, where TCP sockets
453   // cannot be given a binding address, and the platform is expected to pick
454   // the correct local address.
455   //
456   // However, there are two situations in which we allow the bound address to
457   // not be one of the addresses of the requested interface:
458   // 1. The bound address is the loopback address. This happens when a proxy
459   // forces TCP to bind to only the localhost address (see issue 3927).
460   // 2. The bound address is the "any address". This happens when
461   // multiple_routes is disabled (see issue 4780).
462   //
463   // Note that, aside from minor differences in log statements, this logic is
464   // identical to that in TcpPort.
465   const rtc::SocketAddress& socket_address = socket->GetLocalAddress();
466   if (absl::c_none_of(Network()->GetIPs(),
467                       [socket_address](const rtc::InterfaceAddress& addr) {
468                         return socket_address.ipaddr() == addr;
469                       })) {
470     if (socket->GetLocalAddress().IsLoopbackIP()) {
471       RTC_LOG(LS_WARNING) << "Socket is bound to the address:"
472                           << socket_address.ipaddr().ToSensitiveString()
473                           << ", rather than an address associated with network:"
474                           << Network()->ToString()
475                           << ". Still allowing it since it's localhost.";
476     } else if (IPIsAny(Network()->GetBestIP())) {
477       RTC_LOG(LS_WARNING)
478           << "Socket is bound to the address:"
479           << socket_address.ipaddr().ToSensitiveString()
480           << ", rather than an address associated with network:"
481           << Network()->ToString()
482           << ". Still allowing it since it's the 'any' address"
483              ", possibly caused by multiple_routes being disabled.";
484     } else {
485       RTC_LOG(LS_WARNING) << "Socket is bound to the address:"
486                           << socket_address.ipaddr().ToSensitiveString()
487                           << ", rather than an address associated with network:"
488                           << Network()->ToString() << ". Discarding TURN port.";
489       OnAllocateError(
490           STUN_ERROR_GLOBAL_FAILURE,
491           "Address not associated with the desired network interface.");
492       return;
493     }
494   }
495 
496   state_ = STATE_CONNECTED;  // It is ready to send stun requests.
497   if (server_address_.address.IsUnresolvedIP()) {
498     server_address_.address = socket_->GetRemoteAddress();
499   }
500 
501   RTC_LOG(LS_INFO) << "TurnPort connected to "
502                    << socket->GetRemoteAddress().ToSensitiveString()
503                    << " using tcp.";
504   SendRequest(new TurnAllocateRequest(this), 0);
505 }
506 
OnSocketClose(rtc::AsyncPacketSocket * socket,int error)507 void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
508   RTC_LOG(LS_WARNING) << ToString()
509                       << ": Connection with server failed with error: "
510                       << error;
511   RTC_DCHECK(socket == socket_);
512   Close();
513 }
514 
OnAllocateMismatch()515 void TurnPort::OnAllocateMismatch() {
516   if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
517     RTC_LOG(LS_WARNING) << ToString() << ": Giving up on the port after "
518                         << allocate_mismatch_retries_
519                         << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
520     OnAllocateError(STUN_ERROR_ALLOCATION_MISMATCH,
521                     "Maximum retries reached for allocation mismatch.");
522     return;
523   }
524 
525   RTC_LOG(LS_INFO) << ToString()
526                    << ": Allocating a new socket after "
527                       "STUN_ERROR_ALLOCATION_MISMATCH, retry: "
528                    << allocate_mismatch_retries_ + 1;
529   if (SharedSocket()) {
530     ResetSharedSocket();
531   } else {
532     delete socket_;
533   }
534   socket_ = NULL;
535 
536   ResetNonce();
537   PrepareAddress();
538   ++allocate_mismatch_retries_;
539 }
540 
CreateConnection(const Candidate & remote_candidate,CandidateOrigin origin)541 Connection* TurnPort::CreateConnection(const Candidate& remote_candidate,
542                                        CandidateOrigin origin) {
543   // TURN-UDP can only connect to UDP candidates.
544   if (!SupportsProtocol(remote_candidate.protocol())) {
545     return nullptr;
546   }
547 
548   if (state_ == STATE_DISCONNECTED || state_ == STATE_RECEIVEONLY) {
549     return nullptr;
550   }
551 
552   // If the remote endpoint signaled us an mDNS candidate, we do not form a pair
553   // with the relay candidate to avoid IP leakage in the CreatePermission
554   // request.
555   if (absl::EndsWith(remote_candidate.address().hostname(), LOCAL_TLD)) {
556     return nullptr;
557   }
558 
559   // A TURN port will have two candiates, STUN and TURN. STUN may not
560   // present in all cases. If present stun candidate will be added first
561   // and TURN candidate later.
562   for (size_t index = 0; index < Candidates().size(); ++index) {
563     const Candidate& local_candidate = Candidates()[index];
564     if (local_candidate.type() == RELAY_PORT_TYPE &&
565         local_candidate.address().family() ==
566             remote_candidate.address().family()) {
567       // Create an entry, if needed, so we can get our permissions set up
568       // correctly.
569       if (CreateOrRefreshEntry(remote_candidate.address(), next_channel_number_,
570                                remote_candidate.username())) {
571         // An entry was created.
572         next_channel_number_++;
573       }
574       ProxyConnection* conn =
575           new ProxyConnection(this, index, remote_candidate);
576       AddOrReplaceConnection(conn);
577       return conn;
578     }
579   }
580   return nullptr;
581 }
582 
FailAndPruneConnection(const rtc::SocketAddress & address)583 bool TurnPort::FailAndPruneConnection(const rtc::SocketAddress& address) {
584   Connection* conn = GetConnection(address);
585   if (conn != nullptr) {
586     conn->FailAndPrune();
587     return true;
588   }
589   return false;
590 }
591 
SetOption(rtc::Socket::Option opt,int value)592 int TurnPort::SetOption(rtc::Socket::Option opt, int value) {
593   // Remember the last requested DSCP value, for STUN traffic.
594   if (opt == rtc::Socket::OPT_DSCP)
595     stun_dscp_value_ = static_cast<rtc::DiffServCodePoint>(value);
596 
597   if (!socket_) {
598     // If socket is not created yet, these options will be applied during socket
599     // creation.
600     socket_options_[opt] = value;
601     return 0;
602   }
603   return socket_->SetOption(opt, value);
604 }
605 
GetOption(rtc::Socket::Option opt,int * value)606 int TurnPort::GetOption(rtc::Socket::Option opt, int* value) {
607   if (!socket_) {
608     SocketOptionsMap::const_iterator it = socket_options_.find(opt);
609     if (it == socket_options_.end()) {
610       return -1;
611     }
612     *value = it->second;
613     return 0;
614   }
615 
616   return socket_->GetOption(opt, value);
617 }
618 
GetError()619 int TurnPort::GetError() {
620   return error_;
621 }
622 
SendTo(const void * data,size_t size,const rtc::SocketAddress & addr,const rtc::PacketOptions & options,bool payload)623 int TurnPort::SendTo(const void* data,
624                      size_t size,
625                      const rtc::SocketAddress& addr,
626                      const rtc::PacketOptions& options,
627                      bool payload) {
628   // Try to find an entry for this specific address; we should have one.
629   TurnEntry* entry = FindEntry(addr);
630   if (!entry) {
631     RTC_LOG(LS_ERROR) << "Did not find the TurnEntry for address "
632                       << addr.ToSensitiveString();
633     return 0;
634   }
635 
636   if (!ready()) {
637     error_ = ENOTCONN;
638     return SOCKET_ERROR;
639   }
640 
641   // Send the actual contents to the server using the usual mechanism.
642   rtc::PacketOptions modified_options(options);
643   CopyPortInformationToPacketInfo(&modified_options.info_signaled_after_sent);
644   int sent = entry->Send(data, size, payload, modified_options);
645   if (sent <= 0) {
646     return SOCKET_ERROR;
647   }
648 
649   // The caller of the function is expecting the number of user data bytes,
650   // rather than the size of the packet.
651   return static_cast<int>(size);
652 }
653 
CanHandleIncomingPacketsFrom(const rtc::SocketAddress & addr) const654 bool TurnPort::CanHandleIncomingPacketsFrom(
655     const rtc::SocketAddress& addr) const {
656   return server_address_.address == addr;
657 }
658 
HandleIncomingPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,int64_t packet_time_us)659 bool TurnPort::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
660                                     const char* data,
661                                     size_t size,
662                                     const rtc::SocketAddress& remote_addr,
663                                     int64_t packet_time_us) {
664   if (socket != socket_) {
665     // The packet was received on a shared socket after we've allocated a new
666     // socket for this TURN port.
667     return false;
668   }
669 
670   // This is to guard against a STUN response from previous server after
671   // alternative server redirection. TODO(guoweis): add a unit test for this
672   // race condition.
673   if (remote_addr != server_address_.address) {
674     RTC_LOG(LS_WARNING) << ToString()
675                         << ": Discarding TURN message from unknown address: "
676                         << remote_addr.ToSensitiveString()
677                         << " server_address_: "
678                         << server_address_.address.ToSensitiveString();
679     return false;
680   }
681 
682   // The message must be at least the size of a channel header.
683   if (size < TURN_CHANNEL_HEADER_SIZE) {
684     RTC_LOG(LS_WARNING) << ToString()
685                         << ": Received TURN message that was too short";
686     return false;
687   }
688 
689   if (state_ == STATE_DISCONNECTED) {
690     RTC_LOG(LS_WARNING)
691         << ToString()
692         << ": Received TURN message while the TURN port is disconnected";
693     return false;
694   }
695 
696   // Check the message type, to see if is a Channel Data message.
697   // The message will either be channel data, a TURN data indication, or
698   // a response to a previous request.
699   uint16_t msg_type = rtc::GetBE16(data);
700   if (IsTurnChannelData(msg_type)) {
701     HandleChannelData(msg_type, data, size, packet_time_us);
702     return true;
703   }
704 
705   if (msg_type == TURN_DATA_INDICATION) {
706     HandleDataIndication(data, size, packet_time_us);
707     return true;
708   }
709 
710   if (SharedSocket() && (msg_type == STUN_BINDING_RESPONSE ||
711                          msg_type == STUN_BINDING_ERROR_RESPONSE)) {
712     RTC_LOG(LS_VERBOSE)
713         << ToString()
714         << ": Ignoring STUN binding response message on shared socket.";
715     return false;
716   }
717 
718   // This must be a response for one of our requests.
719   // Check success responses, but not errors, for MESSAGE-INTEGRITY.
720   if (IsStunSuccessResponseType(msg_type) &&
721       !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
722     RTC_LOG(LS_WARNING) << ToString()
723                         << ": Received TURN message with invalid "
724                            "message integrity, msg_type: "
725                         << msg_type;
726     return true;
727   }
728   request_manager_.CheckResponse(data, size);
729 
730   return true;
731 }
732 
OnReadPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,const int64_t & packet_time_us)733 void TurnPort::OnReadPacket(rtc::AsyncPacketSocket* socket,
734                             const char* data,
735                             size_t size,
736                             const rtc::SocketAddress& remote_addr,
737                             const int64_t& packet_time_us) {
738   HandleIncomingPacket(socket, data, size, remote_addr, packet_time_us);
739 }
740 
OnSentPacket(rtc::AsyncPacketSocket * socket,const rtc::SentPacket & sent_packet)741 void TurnPort::OnSentPacket(rtc::AsyncPacketSocket* socket,
742                             const rtc::SentPacket& sent_packet) {
743   PortInterface::SignalSentPacket(sent_packet);
744 }
745 
OnReadyToSend(rtc::AsyncPacketSocket * socket)746 void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
747   if (ready()) {
748     Port::OnReadyToSend();
749   }
750 }
751 
SupportsProtocol(const std::string & protocol) const752 bool TurnPort::SupportsProtocol(const std::string& protocol) const {
753   // Turn port only connects to UDP candidates.
754   return protocol == UDP_PROTOCOL_NAME;
755 }
756 
757 // Update current server address port with the alternate server address port.
SetAlternateServer(const rtc::SocketAddress & address)758 bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
759   // Check if we have seen this address before and reject if we did.
760   AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
761   if (iter != attempted_server_addresses_.end()) {
762     RTC_LOG(LS_WARNING) << ToString() << ": Redirection to ["
763                         << address.ToSensitiveString()
764                         << "] ignored, allocation failed.";
765     return false;
766   }
767 
768   // If protocol family of server address doesn't match with local, return.
769   if (!IsCompatibleAddress(address)) {
770     RTC_LOG(LS_WARNING) << "Server IP address family does not match with "
771                            "local host address family type";
772     return false;
773   }
774 
775   // Block redirects to a loopback address.
776   // See: https://bugs.chromium.org/p/chromium/issues/detail?id=649118
777   if (address.IsLoopbackIP()) {
778     RTC_LOG(LS_WARNING) << ToString()
779                         << ": Blocking attempted redirect to loopback address.";
780     return false;
781   }
782 
783   RTC_LOG(LS_INFO) << ToString() << ": Redirecting from TURN server ["
784                    << server_address_.address.ToSensitiveString()
785                    << "] to TURN server [" << address.ToSensitiveString()
786                    << "]";
787   server_address_ = ProtocolAddress(address, server_address_.proto);
788 
789   // Insert the current address to prevent redirection pingpong.
790   attempted_server_addresses_.insert(server_address_.address);
791   return true;
792 }
793 
ResolveTurnAddress(const rtc::SocketAddress & address)794 void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) {
795   if (resolver_)
796     return;
797 
798   RTC_LOG(LS_INFO) << ToString() << ": Starting TURN host lookup for "
799                    << address.ToSensitiveString();
800   resolver_ = socket_factory()->CreateAsyncResolver();
801   resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
802   resolver_->Start(address);
803 }
804 
OnResolveResult(rtc::AsyncResolverInterface * resolver)805 void TurnPort::OnResolveResult(rtc::AsyncResolverInterface* resolver) {
806   RTC_DCHECK(resolver == resolver_);
807   // If DNS resolve is failed when trying to connect to the server using TCP,
808   // one of the reason could be due to DNS queries blocked by firewall.
809   // In such cases we will try to connect to the server with hostname, assuming
810   // socket layer will resolve the hostname through a HTTP proxy (if any).
811   if (resolver_->GetError() != 0 && (server_address_.proto == PROTO_TCP ||
812                                      server_address_.proto == PROTO_TLS)) {
813     if (!CreateTurnClientSocket()) {
814       OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
815                       "TURN host lookup received error.");
816     }
817     return;
818   }
819 
820   // Copy the original server address in |resolved_address|. For TLS based
821   // sockets we need hostname along with resolved address.
822   rtc::SocketAddress resolved_address = server_address_.address;
823   if (resolver_->GetError() != 0 ||
824       !resolver_->GetResolvedAddress(Network()->GetBestIP().family(),
825                                      &resolved_address)) {
826     RTC_LOG(LS_WARNING) << ToString() << ": TURN host lookup received error "
827                         << resolver_->GetError();
828     error_ = resolver_->GetError();
829     OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
830                     "TURN host lookup received error.");
831     return;
832   }
833   // Signal needs both resolved and unresolved address. After signal is sent
834   // we can copy resolved address back into |server_address_|.
835   SignalResolvedServerAddress(this, server_address_.address, resolved_address);
836   server_address_.address = resolved_address;
837   PrepareAddress();
838 }
839 
OnSendStunPacket(const void * data,size_t size,StunRequest * request)840 void TurnPort::OnSendStunPacket(const void* data,
841                                 size_t size,
842                                 StunRequest* request) {
843   RTC_DCHECK(connected());
844   rtc::PacketOptions options(StunDscpValue());
845   options.info_signaled_after_sent.packet_type = rtc::PacketType::kTurnMessage;
846   CopyPortInformationToPacketInfo(&options.info_signaled_after_sent);
847   if (Send(data, size, options) < 0) {
848     RTC_LOG(LS_ERROR) << ToString() << ": Failed to send TURN message, error: "
849                       << socket_->GetError();
850   }
851 }
852 
OnStunAddress(const rtc::SocketAddress & address)853 void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
854   // STUN Port will discover STUN candidate, as it's supplied with first TURN
855   // server address.
856   // Why not using this address? - P2PTransportChannel will start creating
857   // connections after first candidate, which means it could start creating the
858   // connections before TURN candidate added. For that to handle, we need to
859   // supply STUN candidate from this port to UDPPort, and TurnPort should have
860   // handle to UDPPort to pass back the address.
861 }
862 
OnAllocateSuccess(const rtc::SocketAddress & address,const rtc::SocketAddress & stun_address)863 void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
864                                  const rtc::SocketAddress& stun_address) {
865   state_ = STATE_READY;
866 
867   rtc::SocketAddress related_address = stun_address;
868 
869   // For relayed candidate, Base is the candidate itself.
870   AddAddress(address,          // Candidate address.
871              address,          // Base address.
872              related_address,  // Related address.
873              UDP_PROTOCOL_NAME,
874              ProtoToString(server_address_.proto),  // The first hop protocol.
875              "",  // TCP canddiate type, empty for turn candidates.
876              RELAY_PORT_TYPE, GetRelayPreference(server_address_.proto),
877              server_priority_, ReconstructedServerUrl(false /* use_hostname */),
878              true);
879 }
880 
OnAllocateError(int error_code,const std::string & reason)881 void TurnPort::OnAllocateError(int error_code, const std::string& reason) {
882   // We will send SignalPortError asynchronously as this can be sent during
883   // port initialization. This way it will not be blocking other port
884   // creation.
885   thread()->Post(RTC_FROM_HERE, this, MSG_ALLOCATE_ERROR);
886   std::string address = GetLocalAddress().HostAsSensitiveURIString();
887   int port = GetLocalAddress().port();
888   if (server_address_.proto == PROTO_TCP &&
889       server_address_.address.IsPrivateIP()) {
890     address.clear();
891     port = 0;
892   }
893   SignalCandidateError(
894       this, IceCandidateErrorEvent(
895                 address, port, ReconstructedServerUrl(true /* use_hostname */),
896                 error_code, reason));
897 }
898 
OnRefreshError()899 void TurnPort::OnRefreshError() {
900   // Need to clear the requests asynchronously because otherwise, the refresh
901   // request may be deleted twice: once at the end of the message processing
902   // and the other in HandleRefreshError().
903   thread()->Post(RTC_FROM_HERE, this, MSG_REFRESH_ERROR);
904 }
905 
HandleRefreshError()906 void TurnPort::HandleRefreshError() {
907   request_manager_.Clear();
908   state_ = STATE_RECEIVEONLY;
909   // Fail and prune all connections; stop sending data.
910   for (auto kv : connections()) {
911     kv.second->FailAndPrune();
912   }
913 }
914 
Release()915 void TurnPort::Release() {
916   // Remove any pending refresh requests.
917   request_manager_.Clear();
918 
919   // Send refresh with lifetime 0.
920   TurnRefreshRequest* req = new TurnRefreshRequest(this);
921   req->set_lifetime(0);
922   SendRequest(req, 0);
923 
924   state_ = STATE_RECEIVEONLY;
925 }
926 
Close()927 void TurnPort::Close() {
928   if (!ready()) {
929     OnAllocateError(SERVER_NOT_REACHABLE_ERROR, "");
930   }
931   request_manager_.Clear();
932   // Stop the port from creating new connections.
933   state_ = STATE_DISCONNECTED;
934   // Delete all existing connections; stop sending data.
935   for (auto kv : connections()) {
936     kv.second->Destroy();
937   }
938 
939   SignalTurnPortClosed(this);
940 }
941 
StunDscpValue() const942 rtc::DiffServCodePoint TurnPort::StunDscpValue() const {
943   return stun_dscp_value_;
944 }
945 
OnMessage(rtc::Message * message)946 void TurnPort::OnMessage(rtc::Message* message) {
947   switch (message->message_id) {
948     case MSG_ALLOCATE_ERROR:
949       SignalPortError(this);
950       break;
951     case MSG_ALLOCATE_MISMATCH:
952       OnAllocateMismatch();
953       break;
954     case MSG_REFRESH_ERROR:
955       HandleRefreshError();
956       break;
957     case MSG_TRY_ALTERNATE_SERVER:
958       if (server_address().proto == PROTO_UDP) {
959         // Send another allocate request to alternate server, with the received
960         // realm and nonce values.
961         SendRequest(new TurnAllocateRequest(this), 0);
962       } else {
963         // Since it's TCP, we have to delete the connected socket and reconnect
964         // with the alternate server. PrepareAddress will send stun binding once
965         // the new socket is connected.
966         RTC_DCHECK(server_address().proto == PROTO_TCP ||
967                    server_address().proto == PROTO_TLS);
968         RTC_DCHECK(!SharedSocket());
969         delete socket_;
970         socket_ = NULL;
971         PrepareAddress();
972       }
973       break;
974     case MSG_ALLOCATION_RELEASED:
975       Close();
976       break;
977     default:
978       Port::OnMessage(message);
979   }
980 }
981 
OnAllocateRequestTimeout()982 void TurnPort::OnAllocateRequestTimeout() {
983   OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
984                   "TURN allocate request timed out.");
985 }
986 
HandleDataIndication(const char * data,size_t size,int64_t packet_time_us)987 void TurnPort::HandleDataIndication(const char* data,
988                                     size_t size,
989                                     int64_t packet_time_us) {
990   // Read in the message, and process according to RFC5766, Section 10.4.
991   rtc::ByteBufferReader buf(data, size);
992   TurnMessage msg;
993   if (!msg.Read(&buf)) {
994     RTC_LOG(LS_WARNING) << ToString()
995                         << ": Received invalid TURN data indication";
996     return;
997   }
998 
999   // Check mandatory attributes.
1000   const StunAddressAttribute* addr_attr =
1001       msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
1002   if (!addr_attr) {
1003     RTC_LOG(LS_WARNING) << ToString()
1004                         << ": Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
1005                            "in data indication.";
1006     return;
1007   }
1008 
1009   const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
1010   if (!data_attr) {
1011     RTC_LOG(LS_WARNING) << ToString()
1012                         << ": Missing STUN_ATTR_DATA attribute in "
1013                            "data indication.";
1014     return;
1015   }
1016 
1017   // Log a warning if the data didn't come from an address that we think we have
1018   // a permission for.
1019   rtc::SocketAddress ext_addr(addr_attr->GetAddress());
1020   if (!HasPermission(ext_addr.ipaddr())) {
1021     RTC_LOG(LS_WARNING) << ToString()
1022                         << ": Received TURN data indication with unknown "
1023                            "peer address, addr: "
1024                         << ext_addr.ToSensitiveString();
1025   }
1026 
1027   DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr, PROTO_UDP,
1028                  packet_time_us);
1029 }
1030 
HandleChannelData(int channel_id,const char * data,size_t size,int64_t packet_time_us)1031 void TurnPort::HandleChannelData(int channel_id,
1032                                  const char* data,
1033                                  size_t size,
1034                                  int64_t packet_time_us) {
1035   // Read the message, and process according to RFC5766, Section 11.6.
1036   //    0                   1                   2                   3
1037   //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1038   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1039   //   |         Channel Number        |            Length             |
1040   //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1041   //   |                                                               |
1042   //   /                       Application Data                        /
1043   //   /                                                               /
1044   //   |                                                               |
1045   //   |                               +-------------------------------+
1046   //   |                               |
1047   //   +-------------------------------+
1048 
1049   // Extract header fields from the message.
1050   uint16_t len = rtc::GetBE16(data + 2);
1051   if (len > size - TURN_CHANNEL_HEADER_SIZE) {
1052     RTC_LOG(LS_WARNING) << ToString()
1053                         << ": Received TURN channel data message with "
1054                            "incorrect length, len: "
1055                         << len;
1056     return;
1057   }
1058   // Allowing messages larger than |len|, as ChannelData can be padded.
1059 
1060   TurnEntry* entry = FindEntry(channel_id);
1061   if (!entry) {
1062     RTC_LOG(LS_WARNING) << ToString()
1063                         << ": Received TURN channel data message for invalid "
1064                            "channel, channel_id: "
1065                         << channel_id;
1066     return;
1067   }
1068 
1069   DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
1070                  PROTO_UDP, packet_time_us);
1071 }
1072 
DispatchPacket(const char * data,size_t size,const rtc::SocketAddress & remote_addr,ProtocolType proto,int64_t packet_time_us)1073 void TurnPort::DispatchPacket(const char* data,
1074                               size_t size,
1075                               const rtc::SocketAddress& remote_addr,
1076                               ProtocolType proto,
1077                               int64_t packet_time_us) {
1078   if (Connection* conn = GetConnection(remote_addr)) {
1079     conn->OnReadPacket(data, size, packet_time_us);
1080   } else {
1081     Port::OnReadPacket(data, size, remote_addr, proto);
1082   }
1083 }
1084 
ScheduleRefresh(uint32_t lifetime)1085 bool TurnPort::ScheduleRefresh(uint32_t lifetime) {
1086   // Lifetime is in seconds, delay is in milliseconds.
1087   int delay = 1 * 60 * 1000;
1088 
1089   // Cutoff lifetime bigger than 1h.
1090   constexpr uint32_t max_lifetime = 60 * 60;
1091 
1092   if (lifetime < 2 * 60) {
1093     // The RFC does not mention a lower limit on lifetime.
1094     // So if server sends a value less than 2 minutes, we schedule a refresh
1095     // for half lifetime.
1096     RTC_LOG(LS_WARNING) << ToString()
1097                         << ": Received response with short lifetime: "
1098                         << lifetime << " seconds.";
1099     delay = (lifetime * 1000) / 2;
1100   } else if (lifetime > max_lifetime) {
1101     // Make 1 hour largest delay, and then sce
1102     // we schedule a refresh for one minute less than max lifetime.
1103     RTC_LOG(LS_WARNING) << ToString()
1104                         << ": Received response with long lifetime: "
1105                         << lifetime << " seconds.";
1106     delay = (max_lifetime - 60) * 1000;
1107   } else {
1108     // Normal case,
1109     // we schedule a refresh for one minute less than requested lifetime.
1110     delay = (lifetime - 60) * 1000;
1111   }
1112 
1113   SendRequest(new TurnRefreshRequest(this), delay);
1114   RTC_LOG(LS_INFO) << ToString() << ": Scheduled refresh in " << delay << "ms.";
1115   return true;
1116 }
1117 
SendRequest(StunRequest * req,int delay)1118 void TurnPort::SendRequest(StunRequest* req, int delay) {
1119   request_manager_.SendDelayed(req, delay);
1120 }
1121 
AddRequestAuthInfo(StunMessage * msg)1122 void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
1123   // If we've gotten the necessary data from the server, add it to our request.
1124   RTC_DCHECK(!hash_.empty());
1125   msg->AddAttribute(std::make_unique<StunByteStringAttribute>(
1126       STUN_ATTR_USERNAME, credentials_.username));
1127   msg->AddAttribute(
1128       std::make_unique<StunByteStringAttribute>(STUN_ATTR_REALM, realm_));
1129   msg->AddAttribute(
1130       std::make_unique<StunByteStringAttribute>(STUN_ATTR_NONCE, nonce_));
1131   const bool success = msg->AddMessageIntegrity(hash());
1132   RTC_DCHECK(success);
1133 }
1134 
Send(const void * data,size_t len,const rtc::PacketOptions & options)1135 int TurnPort::Send(const void* data,
1136                    size_t len,
1137                    const rtc::PacketOptions& options) {
1138   return socket_->SendTo(data, len, server_address_.address, options);
1139 }
1140 
UpdateHash()1141 void TurnPort::UpdateHash() {
1142   const bool success = ComputeStunCredentialHash(credentials_.username, realm_,
1143                                                  credentials_.password, &hash_);
1144   RTC_DCHECK(success);
1145 }
1146 
UpdateNonce(StunMessage * response)1147 bool TurnPort::UpdateNonce(StunMessage* response) {
1148   // When stale nonce error received, we should update
1149   // hash and store realm and nonce.
1150   // Check the mandatory attributes.
1151   const StunByteStringAttribute* realm_attr =
1152       response->GetByteString(STUN_ATTR_REALM);
1153   if (!realm_attr) {
1154     RTC_LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
1155                          "stale nonce error response.";
1156     return false;
1157   }
1158   set_realm(realm_attr->GetString());
1159 
1160   const StunByteStringAttribute* nonce_attr =
1161       response->GetByteString(STUN_ATTR_NONCE);
1162   if (!nonce_attr) {
1163     RTC_LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
1164                          "stale nonce error response.";
1165     return false;
1166   }
1167   set_nonce(nonce_attr->GetString());
1168   return true;
1169 }
1170 
ResetNonce()1171 void TurnPort::ResetNonce() {
1172   hash_.clear();
1173   nonce_.clear();
1174   realm_.clear();
1175 }
1176 
HasPermission(const rtc::IPAddress & ipaddr) const1177 bool TurnPort::HasPermission(const rtc::IPAddress& ipaddr) const {
1178   return absl::c_any_of(entries_, [&ipaddr](const TurnEntry* e) {
1179     return e->address().ipaddr() == ipaddr;
1180   });
1181 }
1182 
FindEntry(const rtc::SocketAddress & addr) const1183 TurnEntry* TurnPort::FindEntry(const rtc::SocketAddress& addr) const {
1184   auto it = absl::c_find_if(
1185       entries_, [&addr](const TurnEntry* e) { return e->address() == addr; });
1186   return (it != entries_.end()) ? *it : NULL;
1187 }
1188 
FindEntry(int channel_id) const1189 TurnEntry* TurnPort::FindEntry(int channel_id) const {
1190   auto it = absl::c_find_if(entries_, [&channel_id](const TurnEntry* e) {
1191     return e->channel_id() == channel_id;
1192   });
1193   return (it != entries_.end()) ? *it : NULL;
1194 }
1195 
EntryExists(TurnEntry * e)1196 bool TurnPort::EntryExists(TurnEntry* e) {
1197   return absl::c_linear_search(entries_, e);
1198 }
1199 
CreateOrRefreshEntry(const rtc::SocketAddress & addr,int channel_number)1200 bool TurnPort::CreateOrRefreshEntry(const rtc::SocketAddress& addr,
1201                                     int channel_number) {
1202   return CreateOrRefreshEntry(addr, channel_number, "");
1203 }
1204 
CreateOrRefreshEntry(const rtc::SocketAddress & addr,int channel_number,const std::string & remote_ufrag)1205 bool TurnPort::CreateOrRefreshEntry(const rtc::SocketAddress& addr,
1206                                     int channel_number,
1207                                     const std::string& remote_ufrag) {
1208   TurnEntry* entry = FindEntry(addr);
1209   if (entry == nullptr) {
1210     entry = new TurnEntry(this, channel_number, addr, remote_ufrag);
1211     entries_.push_back(entry);
1212     return true;
1213   } else {
1214     if (entry->destruction_timestamp()) {
1215       // Destruction should have only been scheduled (indicated by
1216       // destruction_timestamp being set) if there were no connections using
1217       // this address.
1218       RTC_DCHECK(!GetConnection(addr));
1219       // Resetting the destruction timestamp will ensure that any queued
1220       // destruction tasks, when executed, will see that the timestamp doesn't
1221       // match and do nothing. We do this because (currently) there's not a
1222       // convenient way to cancel queued tasks.
1223       entry->reset_destruction_timestamp();
1224     } else {
1225       // The only valid reason for destruction not being scheduled is that
1226       // there's still one connection.
1227       RTC_DCHECK(GetConnection(addr));
1228     }
1229 
1230     if (webrtc::field_trial::IsEnabled("WebRTC-TurnAddMultiMapping")) {
1231       if (entry->get_remote_ufrag() != remote_ufrag) {
1232         RTC_LOG(LS_INFO) << ToString()
1233                          << ": remote ufrag updated."
1234                             " Sending new permission request";
1235         entry->set_remote_ufrag(remote_ufrag);
1236         entry->SendCreatePermissionRequest(0);
1237       }
1238     }
1239   }
1240   return false;
1241 }
1242 
DestroyEntry(TurnEntry * entry)1243 void TurnPort::DestroyEntry(TurnEntry* entry) {
1244   RTC_DCHECK(entry != NULL);
1245   entry->SignalDestroyed(entry);
1246   entries_.remove(entry);
1247   delete entry;
1248 }
1249 
DestroyEntryIfNotCancelled(TurnEntry * entry,int64_t timestamp)1250 void TurnPort::DestroyEntryIfNotCancelled(TurnEntry* entry, int64_t timestamp) {
1251   if (!EntryExists(entry)) {
1252     return;
1253   }
1254   // The destruction timestamp is used to manage pending destructions. Proceed
1255   // with destruction if it's set, and matches the timestamp from the posted
1256   // task. Note that CreateOrRefreshEntry will unset the timestamp, canceling
1257   // destruction.
1258   if (entry->destruction_timestamp() &&
1259       timestamp == *entry->destruction_timestamp()) {
1260     DestroyEntry(entry);
1261   }
1262 }
1263 
HandleConnectionDestroyed(Connection * conn)1264 void TurnPort::HandleConnectionDestroyed(Connection* conn) {
1265   // Schedule an event to destroy TurnEntry for the connection, which is
1266   // already destroyed.
1267   const rtc::SocketAddress& remote_address = conn->remote_candidate().address();
1268   TurnEntry* entry = FindEntry(remote_address);
1269   RTC_DCHECK(entry != NULL);
1270   ScheduleEntryDestruction(entry);
1271 }
1272 
ScheduleEntryDestruction(TurnEntry * entry)1273 void TurnPort::ScheduleEntryDestruction(TurnEntry* entry) {
1274   RTC_DCHECK(!entry->destruction_timestamp().has_value());
1275   int64_t timestamp = rtc::TimeMillis();
1276   entry->set_destruction_timestamp(timestamp);
1277   invoker_.AsyncInvokeDelayed<void>(
1278       RTC_FROM_HERE, thread(),
1279       rtc::Bind(&TurnPort::DestroyEntryIfNotCancelled, this, entry, timestamp),
1280       TURN_PERMISSION_TIMEOUT);
1281 }
1282 
SetEntryChannelId(const rtc::SocketAddress & address,int channel_id)1283 bool TurnPort::SetEntryChannelId(const rtc::SocketAddress& address,
1284                                  int channel_id) {
1285   TurnEntry* entry = FindEntry(address);
1286   if (!entry) {
1287     return false;
1288   }
1289   entry->set_channel_id(channel_id);
1290   return true;
1291 }
1292 
ReconstructedServerUrl(bool use_hostname)1293 std::string TurnPort::ReconstructedServerUrl(bool use_hostname) {
1294   // draft-petithuguenin-behave-turn-uris-01
1295   // turnURI       = scheme ":" turn-host [ ":" turn-port ]
1296   //                 [ "?transport=" transport ]
1297   // scheme        = "turn" / "turns"
1298   // transport     = "udp" / "tcp" / transport-ext
1299   // transport-ext = 1*unreserved
1300   // turn-host     = IP-literal / IPv4address / reg-name
1301   // turn-port     = *DIGIT
1302   std::string scheme = "turn";
1303   std::string transport = "tcp";
1304   switch (server_address_.proto) {
1305     case PROTO_SSLTCP:
1306     case PROTO_TLS:
1307       scheme = "turns";
1308       break;
1309     case PROTO_UDP:
1310       transport = "udp";
1311       break;
1312     case PROTO_TCP:
1313       break;
1314   }
1315   rtc::StringBuilder url;
1316   url << scheme << ":"
1317       << (use_hostname ? server_address_.address.hostname()
1318                        : server_address_.address.ipaddr().ToString())
1319       << ":" << server_address_.address.port() << "?transport=" << transport;
1320   return url.Release();
1321 }
1322 
TurnCustomizerMaybeModifyOutgoingStunMessage(StunMessage * message)1323 void TurnPort::TurnCustomizerMaybeModifyOutgoingStunMessage(
1324     StunMessage* message) {
1325   if (turn_customizer_ == nullptr) {
1326     return;
1327   }
1328 
1329   turn_customizer_->MaybeModifyOutgoingStunMessage(this, message);
1330 }
1331 
TurnCustomizerAllowChannelData(const void * data,size_t size,bool payload)1332 bool TurnPort::TurnCustomizerAllowChannelData(const void* data,
1333                                               size_t size,
1334                                               bool payload) {
1335   if (turn_customizer_ == nullptr) {
1336     return true;
1337   }
1338 
1339   return turn_customizer_->AllowChannelData(this, data, size, payload);
1340 }
1341 
MaybeAddTurnLoggingId(StunMessage * msg)1342 void TurnPort::MaybeAddTurnLoggingId(StunMessage* msg) {
1343   if (!turn_logging_id_.empty()) {
1344     msg->AddAttribute(std::make_unique<StunByteStringAttribute>(
1345         STUN_ATTR_TURN_LOGGING_ID, turn_logging_id_));
1346   }
1347 }
1348 
TurnAllocateRequest(TurnPort * port)1349 TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
1350     : StunRequest(new TurnMessage()), port_(port) {}
1351 
Prepare(StunMessage * request)1352 void TurnAllocateRequest::Prepare(StunMessage* request) {
1353   // Create the request as indicated in RFC 5766, Section 6.1.
1354   request->SetType(TURN_ALLOCATE_REQUEST);
1355   auto transport_attr =
1356       StunAttribute::CreateUInt32(STUN_ATTR_REQUESTED_TRANSPORT);
1357   transport_attr->SetValue(IPPROTO_UDP << 24);
1358   request->AddAttribute(std::move(transport_attr));
1359   if (!port_->hash().empty()) {
1360     port_->AddRequestAuthInfo(request);
1361   }
1362   port_->MaybeAddTurnLoggingId(request);
1363   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(request);
1364 }
1365 
OnSent()1366 void TurnAllocateRequest::OnSent() {
1367   RTC_LOG(LS_INFO) << port_->ToString() << ": TURN allocate request sent, id="
1368                    << rtc::hex_encode(id());
1369   StunRequest::OnSent();
1370 }
1371 
OnResponse(StunMessage * response)1372 void TurnAllocateRequest::OnResponse(StunMessage* response) {
1373   RTC_LOG(LS_INFO) << port_->ToString()
1374                    << ": TURN allocate requested successfully, id="
1375                    << rtc::hex_encode(id())
1376                    << ", code=0"  // Makes logging easier to parse.
1377                       ", rtt="
1378                    << Elapsed();
1379 
1380   // Check mandatory attributes as indicated in RFC5766, Section 6.3.
1381   const StunAddressAttribute* mapped_attr =
1382       response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1383   if (!mapped_attr) {
1384     RTC_LOG(LS_WARNING) << port_->ToString()
1385                         << ": Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
1386                            "attribute in allocate success response";
1387     return;
1388   }
1389   // Using XOR-Mapped-Address for stun.
1390   port_->OnStunAddress(mapped_attr->GetAddress());
1391 
1392   const StunAddressAttribute* relayed_attr =
1393       response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
1394   if (!relayed_attr) {
1395     RTC_LOG(LS_WARNING) << port_->ToString()
1396                         << ": Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
1397                            "attribute in allocate success response";
1398     return;
1399   }
1400 
1401   const StunUInt32Attribute* lifetime_attr =
1402       response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
1403   if (!lifetime_attr) {
1404     RTC_LOG(LS_WARNING) << port_->ToString()
1405                         << ": Missing STUN_ATTR_TURN_LIFETIME attribute in "
1406                            "allocate success response";
1407     return;
1408   }
1409   // Notify the port the allocate succeeded, and schedule a refresh request.
1410   port_->OnAllocateSuccess(relayed_attr->GetAddress(),
1411                            mapped_attr->GetAddress());
1412   port_->ScheduleRefresh(lifetime_attr->value());
1413 }
1414 
OnErrorResponse(StunMessage * response)1415 void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
1416   // Process error response according to RFC5766, Section 6.4.
1417   int error_code = response->GetErrorCodeValue();
1418 
1419   RTC_LOG(LS_INFO) << port_->ToString()
1420                    << ": Received TURN allocate error response, id="
1421                    << rtc::hex_encode(id()) << ", code=" << error_code
1422                    << ", rtt=" << Elapsed();
1423 
1424   switch (error_code) {
1425     case STUN_ERROR_UNAUTHORIZED:  // Unauthrorized.
1426       OnAuthChallenge(response, error_code);
1427       break;
1428     case STUN_ERROR_TRY_ALTERNATE:
1429       OnTryAlternate(response, error_code);
1430       break;
1431     case STUN_ERROR_ALLOCATION_MISMATCH:
1432       // We must handle this error async because trying to delete the socket in
1433       // OnErrorResponse will cause a deadlock on the socket.
1434       port_->thread()->Post(RTC_FROM_HERE, port_,
1435                             TurnPort::MSG_ALLOCATE_MISMATCH);
1436       break;
1437     default:
1438       RTC_LOG(LS_WARNING) << port_->ToString()
1439                           << ": Received TURN allocate error response, id="
1440                           << rtc::hex_encode(id()) << ", code=" << error_code
1441                           << ", rtt=" << Elapsed();
1442       const StunErrorCodeAttribute* attr = response->GetErrorCode();
1443       port_->OnAllocateError(error_code, attr ? attr->reason() : "");
1444   }
1445 }
1446 
OnTimeout()1447 void TurnAllocateRequest::OnTimeout() {
1448   RTC_LOG(LS_WARNING) << port_->ToString() << ": TURN allocate request "
1449                       << rtc::hex_encode(id()) << " timeout";
1450   port_->OnAllocateRequestTimeout();
1451 }
1452 
OnAuthChallenge(StunMessage * response,int code)1453 void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
1454   // If we failed to authenticate even after we sent our credentials, fail hard.
1455   if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
1456     RTC_LOG(LS_WARNING) << port_->ToString()
1457                         << ": Failed to authenticate with the server "
1458                            "after challenge.";
1459     const StunErrorCodeAttribute* attr = response->GetErrorCode();
1460     port_->OnAllocateError(STUN_ERROR_UNAUTHORIZED, attr ? attr->reason() : "");
1461     return;
1462   }
1463 
1464   // Check the mandatory attributes.
1465   const StunByteStringAttribute* realm_attr =
1466       response->GetByteString(STUN_ATTR_REALM);
1467   if (!realm_attr) {
1468     RTC_LOG(LS_WARNING) << port_->ToString()
1469                         << ": Missing STUN_ATTR_REALM attribute in "
1470                            "allocate unauthorized response.";
1471     return;
1472   }
1473   port_->set_realm(realm_attr->GetString());
1474 
1475   const StunByteStringAttribute* nonce_attr =
1476       response->GetByteString(STUN_ATTR_NONCE);
1477   if (!nonce_attr) {
1478     RTC_LOG(LS_WARNING) << port_->ToString()
1479                         << ": Missing STUN_ATTR_NONCE attribute in "
1480                            "allocate unauthorized response.";
1481     return;
1482   }
1483   port_->set_nonce(nonce_attr->GetString());
1484 
1485   // Send another allocate request, with the received realm and nonce values.
1486   port_->SendRequest(new TurnAllocateRequest(port_), 0);
1487 }
1488 
OnTryAlternate(StunMessage * response,int code)1489 void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
1490   // According to RFC 5389 section 11, there are use cases where
1491   // authentication of response is not possible, we're not validating
1492   // message integrity.
1493   const StunErrorCodeAttribute* error_code_attr = response->GetErrorCode();
1494   // Get the alternate server address attribute value.
1495   const StunAddressAttribute* alternate_server_attr =
1496       response->GetAddress(STUN_ATTR_ALTERNATE_SERVER);
1497   if (!alternate_server_attr) {
1498     RTC_LOG(LS_WARNING) << port_->ToString()
1499                         << ": Missing STUN_ATTR_ALTERNATE_SERVER "
1500                            "attribute in try alternate error response";
1501     port_->OnAllocateError(STUN_ERROR_TRY_ALTERNATE,
1502                            error_code_attr ? error_code_attr->reason() : "");
1503     return;
1504   }
1505   if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) {
1506     port_->OnAllocateError(STUN_ERROR_TRY_ALTERNATE,
1507                            error_code_attr ? error_code_attr->reason() : "");
1508     return;
1509   }
1510 
1511   // Check the attributes.
1512   const StunByteStringAttribute* realm_attr =
1513       response->GetByteString(STUN_ATTR_REALM);
1514   if (realm_attr) {
1515     RTC_LOG(LS_INFO) << port_->ToString()
1516                      << ": Applying STUN_ATTR_REALM attribute in "
1517                         "try alternate error response.";
1518     port_->set_realm(realm_attr->GetString());
1519   }
1520 
1521   const StunByteStringAttribute* nonce_attr =
1522       response->GetByteString(STUN_ATTR_NONCE);
1523   if (nonce_attr) {
1524     RTC_LOG(LS_INFO) << port_->ToString()
1525                      << ": Applying STUN_ATTR_NONCE attribute in "
1526                         "try alternate error response.";
1527     port_->set_nonce(nonce_attr->GetString());
1528   }
1529 
1530   // For TCP, we can't close the original Tcp socket during handling a 300 as
1531   // we're still inside that socket's event handler. Doing so will cause
1532   // deadlock.
1533   port_->thread()->Post(RTC_FROM_HERE, port_,
1534                         TurnPort::MSG_TRY_ALTERNATE_SERVER);
1535 }
1536 
TurnRefreshRequest(TurnPort * port)1537 TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
1538     : StunRequest(new TurnMessage()), port_(port), lifetime_(-1) {}
1539 
Prepare(StunMessage * request)1540 void TurnRefreshRequest::Prepare(StunMessage* request) {
1541   // Create the request as indicated in RFC 5766, Section 7.1.
1542   // No attributes need to be included.
1543   request->SetType(TURN_REFRESH_REQUEST);
1544   if (lifetime_ > -1) {
1545     request->AddAttribute(
1546         std::make_unique<StunUInt32Attribute>(STUN_ATTR_LIFETIME, lifetime_));
1547   }
1548 
1549   port_->AddRequestAuthInfo(request);
1550   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(request);
1551 }
1552 
OnSent()1553 void TurnRefreshRequest::OnSent() {
1554   RTC_LOG(LS_INFO) << port_->ToString() << ": TURN refresh request sent, id="
1555                    << rtc::hex_encode(id());
1556   StunRequest::OnSent();
1557 }
1558 
OnResponse(StunMessage * response)1559 void TurnRefreshRequest::OnResponse(StunMessage* response) {
1560   RTC_LOG(LS_INFO) << port_->ToString()
1561                    << ": TURN refresh requested successfully, id="
1562                    << rtc::hex_encode(id())
1563                    << ", code=0"  // Makes logging easier to parse.
1564                       ", rtt="
1565                    << Elapsed();
1566 
1567   // Check mandatory attributes as indicated in RFC5766, Section 7.3.
1568   const StunUInt32Attribute* lifetime_attr =
1569       response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
1570   if (!lifetime_attr) {
1571     RTC_LOG(LS_WARNING) << port_->ToString()
1572                         << ": Missing STUN_ATTR_TURN_LIFETIME attribute in "
1573                            "refresh success response.";
1574     return;
1575   }
1576 
1577   if (lifetime_attr->value() > 0) {
1578     // Schedule a refresh based on the returned lifetime value.
1579     port_->ScheduleRefresh(lifetime_attr->value());
1580   } else {
1581     // If we scheduled a refresh with lifetime 0, we're releasing this
1582     // allocation; see TurnPort::Release.
1583     port_->thread()->Post(RTC_FROM_HERE, port_,
1584                           TurnPort::MSG_ALLOCATION_RELEASED);
1585   }
1586 
1587   port_->SignalTurnRefreshResult(port_, TURN_SUCCESS_RESULT_CODE);
1588 }
1589 
OnErrorResponse(StunMessage * response)1590 void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
1591   int error_code = response->GetErrorCodeValue();
1592 
1593   if (error_code == STUN_ERROR_STALE_NONCE) {
1594     if (port_->UpdateNonce(response)) {
1595       // Send RefreshRequest immediately.
1596       port_->SendRequest(new TurnRefreshRequest(port_), 0);
1597     }
1598   } else {
1599     RTC_LOG(LS_WARNING) << port_->ToString()
1600                         << ": Received TURN refresh error response, id="
1601                         << rtc::hex_encode(id()) << ", code=" << error_code
1602                         << ", rtt=" << Elapsed();
1603     port_->OnRefreshError();
1604     port_->SignalTurnRefreshResult(port_, error_code);
1605   }
1606 }
1607 
OnTimeout()1608 void TurnRefreshRequest::OnTimeout() {
1609   RTC_LOG(LS_WARNING) << port_->ToString() << ": TURN refresh timeout "
1610                       << rtc::hex_encode(id());
1611   port_->OnRefreshError();
1612 }
1613 
TurnCreatePermissionRequest(TurnPort * port,TurnEntry * entry,const rtc::SocketAddress & ext_addr,const std::string & remote_ufrag)1614 TurnCreatePermissionRequest::TurnCreatePermissionRequest(
1615     TurnPort* port,
1616     TurnEntry* entry,
1617     const rtc::SocketAddress& ext_addr,
1618     const std::string& remote_ufrag)
1619     : StunRequest(new TurnMessage()),
1620       port_(port),
1621       entry_(entry),
1622       ext_addr_(ext_addr),
1623       remote_ufrag_(remote_ufrag) {
1624   entry_->SignalDestroyed.connect(
1625       this, &TurnCreatePermissionRequest::OnEntryDestroyed);
1626 }
1627 
Prepare(StunMessage * request)1628 void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
1629   // Create the request as indicated in RFC5766, Section 9.1.
1630   request->SetType(TURN_CREATE_PERMISSION_REQUEST);
1631   request->AddAttribute(std::make_unique<StunXorAddressAttribute>(
1632       STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
1633   if (webrtc::field_trial::IsEnabled("WebRTC-TurnAddMultiMapping")) {
1634     request->AddAttribute(std::make_unique<cricket::StunByteStringAttribute>(
1635         STUN_ATTR_MULTI_MAPPING, remote_ufrag_));
1636   }
1637   port_->AddRequestAuthInfo(request);
1638   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(request);
1639 }
1640 
OnSent()1641 void TurnCreatePermissionRequest::OnSent() {
1642   RTC_LOG(LS_INFO) << port_->ToString()
1643                    << ": TURN create permission request sent, id="
1644                    << rtc::hex_encode(id());
1645   StunRequest::OnSent();
1646 }
1647 
OnResponse(StunMessage * response)1648 void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
1649   RTC_LOG(LS_INFO) << port_->ToString()
1650                    << ": TURN permission requested successfully, id="
1651                    << rtc::hex_encode(id())
1652                    << ", code=0"  // Makes logging easier to parse.
1653                       ", rtt="
1654                    << Elapsed();
1655 
1656   if (entry_) {
1657     entry_->OnCreatePermissionSuccess();
1658   }
1659 }
1660 
OnErrorResponse(StunMessage * response)1661 void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
1662   int error_code = response->GetErrorCodeValue();
1663   RTC_LOG(LS_WARNING) << port_->ToString()
1664                       << ": Received TURN create permission error response, id="
1665                       << rtc::hex_encode(id()) << ", code=" << error_code
1666                       << ", rtt=" << Elapsed();
1667   if (entry_) {
1668     entry_->OnCreatePermissionError(response, error_code);
1669   }
1670 }
1671 
OnTimeout()1672 void TurnCreatePermissionRequest::OnTimeout() {
1673   RTC_LOG(LS_WARNING) << port_->ToString()
1674                       << ": TURN create permission timeout "
1675                       << rtc::hex_encode(id());
1676   if (entry_) {
1677     entry_->OnCreatePermissionTimeout();
1678   }
1679 }
1680 
OnEntryDestroyed(TurnEntry * entry)1681 void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
1682   RTC_DCHECK(entry_ == entry);
1683   entry_ = NULL;
1684 }
1685 
TurnChannelBindRequest(TurnPort * port,TurnEntry * entry,int channel_id,const rtc::SocketAddress & ext_addr)1686 TurnChannelBindRequest::TurnChannelBindRequest(
1687     TurnPort* port,
1688     TurnEntry* entry,
1689     int channel_id,
1690     const rtc::SocketAddress& ext_addr)
1691     : StunRequest(new TurnMessage()),
1692       port_(port),
1693       entry_(entry),
1694       channel_id_(channel_id),
1695       ext_addr_(ext_addr) {
1696   entry_->SignalDestroyed.connect(this,
1697                                   &TurnChannelBindRequest::OnEntryDestroyed);
1698 }
1699 
Prepare(StunMessage * request)1700 void TurnChannelBindRequest::Prepare(StunMessage* request) {
1701   // Create the request as indicated in RFC5766, Section 11.1.
1702   request->SetType(TURN_CHANNEL_BIND_REQUEST);
1703   request->AddAttribute(std::make_unique<StunUInt32Attribute>(
1704       STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16));
1705   request->AddAttribute(std::make_unique<StunXorAddressAttribute>(
1706       STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
1707   port_->AddRequestAuthInfo(request);
1708   port_->TurnCustomizerMaybeModifyOutgoingStunMessage(request);
1709 }
1710 
OnSent()1711 void TurnChannelBindRequest::OnSent() {
1712   RTC_LOG(LS_INFO) << port_->ToString()
1713                    << ": TURN channel bind request sent, id="
1714                    << rtc::hex_encode(id());
1715   StunRequest::OnSent();
1716 }
1717 
OnResponse(StunMessage * response)1718 void TurnChannelBindRequest::OnResponse(StunMessage* response) {
1719   RTC_LOG(LS_INFO) << port_->ToString()
1720                    << ": TURN channel bind requested successfully, id="
1721                    << rtc::hex_encode(id())
1722                    << ", code=0"  // Makes logging easier to parse.
1723                       ", rtt="
1724                    << Elapsed();
1725 
1726   if (entry_) {
1727     entry_->OnChannelBindSuccess();
1728     // Refresh the channel binding just under the permission timeout
1729     // threshold. The channel binding has a longer lifetime, but
1730     // this is the easiest way to keep both the channel and the
1731     // permission from expiring.
1732     int delay = TURN_PERMISSION_TIMEOUT - 60000;
1733     entry_->SendChannelBindRequest(delay);
1734     RTC_LOG(LS_INFO) << port_->ToString() << ": Scheduled channel bind in "
1735                      << delay << "ms.";
1736   }
1737 }
1738 
OnErrorResponse(StunMessage * response)1739 void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
1740   int error_code = response->GetErrorCodeValue();
1741   RTC_LOG(LS_WARNING) << port_->ToString()
1742                       << ": Received TURN channel bind error response, id="
1743                       << rtc::hex_encode(id()) << ", code=" << error_code
1744                       << ", rtt=" << Elapsed();
1745   if (entry_) {
1746     entry_->OnChannelBindError(response, error_code);
1747   }
1748 }
1749 
OnTimeout()1750 void TurnChannelBindRequest::OnTimeout() {
1751   RTC_LOG(LS_WARNING) << port_->ToString() << ": TURN channel bind timeout "
1752                       << rtc::hex_encode(id());
1753   if (entry_) {
1754     entry_->OnChannelBindTimeout();
1755   }
1756 }
1757 
OnEntryDestroyed(TurnEntry * entry)1758 void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
1759   RTC_DCHECK(entry_ == entry);
1760   entry_ = NULL;
1761 }
1762 
TurnEntry(TurnPort * port,int channel_id,const rtc::SocketAddress & ext_addr,const std::string remote_ufrag)1763 TurnEntry::TurnEntry(TurnPort* port,
1764                      int channel_id,
1765                      const rtc::SocketAddress& ext_addr,
1766                      const std::string remote_ufrag)
1767     : port_(port),
1768       channel_id_(channel_id),
1769       ext_addr_(ext_addr),
1770       state_(STATE_UNBOUND),
1771       remote_ufrag_(remote_ufrag) {
1772   // Creating permission for |ext_addr_|.
1773   SendCreatePermissionRequest(0);
1774 }
1775 
SendCreatePermissionRequest(int delay)1776 void TurnEntry::SendCreatePermissionRequest(int delay) {
1777   port_->SendRequest(
1778       new TurnCreatePermissionRequest(port_, this, ext_addr_, remote_ufrag_),
1779       delay);
1780 }
1781 
SendChannelBindRequest(int delay)1782 void TurnEntry::SendChannelBindRequest(int delay) {
1783   port_->SendRequest(
1784       new TurnChannelBindRequest(port_, this, channel_id_, ext_addr_), delay);
1785 }
1786 
Send(const void * data,size_t size,bool payload,const rtc::PacketOptions & options)1787 int TurnEntry::Send(const void* data,
1788                     size_t size,
1789                     bool payload,
1790                     const rtc::PacketOptions& options) {
1791   rtc::ByteBufferWriter buf;
1792   if (state_ != STATE_BOUND ||
1793       !port_->TurnCustomizerAllowChannelData(data, size, payload)) {
1794     // If we haven't bound the channel yet, we have to use a Send Indication.
1795     // The turn_customizer_ can also make us use Send Indication.
1796     TurnMessage msg;
1797     msg.SetType(TURN_SEND_INDICATION);
1798     msg.SetTransactionID(rtc::CreateRandomString(kStunTransactionIdLength));
1799     msg.AddAttribute(std::make_unique<StunXorAddressAttribute>(
1800         STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_));
1801     msg.AddAttribute(
1802         std::make_unique<StunByteStringAttribute>(STUN_ATTR_DATA, data, size));
1803 
1804     port_->TurnCustomizerMaybeModifyOutgoingStunMessage(&msg);
1805 
1806     const bool success = msg.Write(&buf);
1807     RTC_DCHECK(success);
1808 
1809     // If we're sending real data, request a channel bind that we can use later.
1810     if (state_ == STATE_UNBOUND && payload) {
1811       SendChannelBindRequest(0);
1812       state_ = STATE_BINDING;
1813     }
1814   } else {
1815     // If the channel is bound, we can send the data as a Channel Message.
1816     buf.WriteUInt16(channel_id_);
1817     buf.WriteUInt16(static_cast<uint16_t>(size));
1818     buf.WriteBytes(reinterpret_cast<const char*>(data), size);
1819   }
1820   rtc::PacketOptions modified_options(options);
1821   modified_options.info_signaled_after_sent.turn_overhead_bytes =
1822       buf.Length() - size;
1823   return port_->Send(buf.Data(), buf.Length(), modified_options);
1824 }
1825 
OnCreatePermissionSuccess()1826 void TurnEntry::OnCreatePermissionSuccess() {
1827   RTC_LOG(LS_INFO) << port_->ToString() << ": Create permission for "
1828                    << ext_addr_.ToSensitiveString() << " succeeded";
1829   port_->SignalCreatePermissionResult(port_, ext_addr_,
1830                                       TURN_SUCCESS_RESULT_CODE);
1831 
1832   // If |state_| is STATE_BOUND, the permission will be refreshed
1833   // by ChannelBindRequest.
1834   if (state_ != STATE_BOUND) {
1835     // Refresh the permission request about 1 minute before the permission
1836     // times out.
1837     int delay = TURN_PERMISSION_TIMEOUT - 60000;
1838     SendCreatePermissionRequest(delay);
1839     RTC_LOG(LS_INFO) << port_->ToString()
1840                      << ": Scheduled create-permission-request in " << delay
1841                      << "ms.";
1842   }
1843 }
1844 
OnCreatePermissionError(StunMessage * response,int code)1845 void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
1846   if (code == STUN_ERROR_STALE_NONCE) {
1847     if (port_->UpdateNonce(response)) {
1848       SendCreatePermissionRequest(0);
1849     }
1850   } else {
1851     bool found = port_->FailAndPruneConnection(ext_addr_);
1852     if (found) {
1853       RTC_LOG(LS_ERROR) << "Received TURN CreatePermission error response, "
1854                            "code="
1855                         << code << "; pruned connection.";
1856     }
1857     // Send signal with error code.
1858     port_->SignalCreatePermissionResult(port_, ext_addr_, code);
1859   }
1860 }
1861 
OnCreatePermissionTimeout()1862 void TurnEntry::OnCreatePermissionTimeout() {
1863   port_->FailAndPruneConnection(ext_addr_);
1864 }
1865 
OnChannelBindSuccess()1866 void TurnEntry::OnChannelBindSuccess() {
1867   RTC_LOG(LS_INFO) << port_->ToString() << ": Successful channel bind for "
1868                    << ext_addr_.ToSensitiveString();
1869   RTC_DCHECK(state_ == STATE_BINDING || state_ == STATE_BOUND);
1870   state_ = STATE_BOUND;
1871 }
1872 
OnChannelBindError(StunMessage * response,int code)1873 void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1874   // If the channel bind fails due to errors other than STATE_NONCE,
1875   // we will fail and prune the connection and rely on ICE restart to
1876   // re-establish a new connection if needed.
1877   if (code == STUN_ERROR_STALE_NONCE) {
1878     if (port_->UpdateNonce(response)) {
1879       // Send channel bind request with fresh nonce.
1880       SendChannelBindRequest(0);
1881     }
1882   } else {
1883     state_ = STATE_UNBOUND;
1884     port_->FailAndPruneConnection(ext_addr_);
1885   }
1886 }
OnChannelBindTimeout()1887 void TurnEntry::OnChannelBindTimeout() {
1888   state_ = STATE_UNBOUND;
1889   port_->FailAndPruneConnection(ext_addr_);
1890 }
1891 }  // namespace cricket
1892