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