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