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