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