blob: 3fdcac5f31b5804d094d8fe6e8a5891f7a8dd94e [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
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 "webrtc/p2p/base/turnport.h"
12
13#include <functional>
14
15#include "webrtc/p2p/base/common.h"
16#include "webrtc/p2p/base/stun.h"
17#include "webrtc/base/asyncpacketsocket.h"
18#include "webrtc/base/byteorder.h"
19#include "webrtc/base/common.h"
20#include "webrtc/base/logging.h"
21#include "webrtc/base/nethelpers.h"
22#include "webrtc/base/socketaddress.h"
23#include "webrtc/base/stringencode.h"
24
25namespace cricket {
26
27// TODO(juberti): Move to stun.h when relay messages have been renamed.
28static const int TURN_ALLOCATE_REQUEST = STUN_ALLOCATE_REQUEST;
29
30// TODO(juberti): Extract to turnmessage.h
31static const int TURN_DEFAULT_PORT = 3478;
32static const int TURN_CHANNEL_NUMBER_START = 0x4000;
33static const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
34
35static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
36
37// Retry at most twice (i.e. three different ALLOCATE requests) on
38// STUN_ERROR_ALLOCATION_MISMATCH error per rfc5766.
39static const size_t MAX_ALLOCATE_MISMATCH_RETRIES = 2;
40
Peter Boström0c4e06b2015-10-07 12:23:21 +020041inline bool IsTurnChannelData(uint16_t msg_type) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000042 return ((msg_type & 0xC000) == 0x4000); // MSB are 0b01
43}
44
45static int GetRelayPreference(cricket::ProtocolType proto, bool secure) {
46 int relay_preference = ICE_TYPE_PREFERENCE_RELAY;
47 if (proto == cricket::PROTO_TCP) {
48 relay_preference -= 1;
49 if (secure)
50 relay_preference -= 1;
51 }
52
53 ASSERT(relay_preference >= 0);
54 return relay_preference;
55}
56
57class TurnAllocateRequest : public StunRequest {
58 public:
59 explicit TurnAllocateRequest(TurnPort* port);
Peter Thatcher1cf6f812015-05-15 10:40:45 -070060 void Prepare(StunMessage* request) override;
61 void OnSent() override;
62 void OnResponse(StunMessage* response) override;
63 void OnErrorResponse(StunMessage* response) override;
64 void OnTimeout() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000065
66 private:
67 // Handles authentication challenge from the server.
68 void OnAuthChallenge(StunMessage* response, int code);
69 void OnTryAlternate(StunMessage* response, int code);
70 void OnUnknownAttribute(StunMessage* response);
71
72 TurnPort* port_;
73};
74
75class TurnRefreshRequest : public StunRequest {
76 public:
77 explicit TurnRefreshRequest(TurnPort* port);
Peter Thatcher1cf6f812015-05-15 10:40:45 -070078 void Prepare(StunMessage* request) override;
79 void OnSent() override;
80 void OnResponse(StunMessage* response) override;
81 void OnErrorResponse(StunMessage* response) override;
82 void OnTimeout() override;
pthatcher@webrtc.orgfe672e32015-01-17 00:58:15 +000083 void set_lifetime(int lifetime) { lifetime_ = lifetime; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000084
85 private:
86 TurnPort* port_;
pthatcher@webrtc.orgfe672e32015-01-17 00:58:15 +000087 int lifetime_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000088};
89
90class TurnCreatePermissionRequest : public StunRequest,
91 public sigslot::has_slots<> {
92 public:
93 TurnCreatePermissionRequest(TurnPort* port, TurnEntry* entry,
94 const rtc::SocketAddress& ext_addr);
Peter Thatcher1cf6f812015-05-15 10:40:45 -070095 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;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000100
101 private:
102 void OnEntryDestroyed(TurnEntry* entry);
103
104 TurnPort* port_;
105 TurnEntry* entry_;
106 rtc::SocketAddress ext_addr_;
107};
108
109class TurnChannelBindRequest : public StunRequest,
110 public sigslot::has_slots<> {
111 public:
112 TurnChannelBindRequest(TurnPort* port, TurnEntry* entry, int channel_id,
113 const rtc::SocketAddress& ext_addr);
Peter Thatcher1cf6f812015-05-15 10:40:45 -0700114 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;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000119
120 private:
121 void OnEntryDestroyed(TurnEntry* entry);
122
123 TurnPort* port_;
124 TurnEntry* entry_;
125 int channel_id_;
126 rtc::SocketAddress ext_addr_;
127};
128
129// Manages a "connection" to a remote destination. We will attempt to bring up
130// a channel for this remote destination to reduce the overhead of sending data.
131class TurnEntry : public sigslot::has_slots<> {
132 public:
133 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
134 TurnEntry(TurnPort* port, int channel_id,
135 const rtc::SocketAddress& ext_addr);
136
137 TurnPort* port() { return port_; }
138
139 int channel_id() const { return channel_id_; }
140 const rtc::SocketAddress& address() const { return ext_addr_; }
141 BindState state() const { return state_; }
142
143 // Helper methods to send permission and channel bind requests.
144 void SendCreatePermissionRequest();
145 void SendChannelBindRequest(int delay);
146 // Sends a packet to the given destination address.
147 // This will wrap the packet in STUN if necessary.
148 int Send(const void* data, size_t size, bool payload,
149 const rtc::PacketOptions& options);
150
151 void OnCreatePermissionSuccess();
152 void OnCreatePermissionError(StunMessage* response, int code);
153 void OnChannelBindSuccess();
154 void OnChannelBindError(StunMessage* response, int code);
155 // Signal sent when TurnEntry is destroyed.
156 sigslot::signal1<TurnEntry*> SignalDestroyed;
157
158 private:
159 TurnPort* port_;
160 int channel_id_;
161 rtc::SocketAddress ext_addr_;
162 BindState state_;
163};
164
165TurnPort::TurnPort(rtc::Thread* thread,
166 rtc::PacketSocketFactory* factory,
167 rtc::Network* network,
168 rtc::AsyncPacketSocket* socket,
169 const std::string& username,
170 const std::string& password,
171 const ProtocolAddress& server_address,
172 const RelayCredentials& credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000173 int server_priority,
174 const std::string& origin)
honghaizb19eba32015-08-03 10:23:31 -0700175 : Port(thread,
176 factory,
177 network,
178 socket->GetLocalAddress().ipaddr(),
179 username,
180 password),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000181 server_address_(server_address),
182 credentials_(credentials),
183 socket_(socket),
184 resolver_(NULL),
185 error_(0),
186 request_manager_(thread),
187 next_channel_number_(TURN_CHANNEL_NUMBER_START),
honghaizb19eba32015-08-03 10:23:31 -0700188 state_(STATE_CONNECTING),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000189 server_priority_(server_priority),
190 allocate_mismatch_retries_(0) {
191 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000192 request_manager_.set_origin(origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000193}
194
195TurnPort::TurnPort(rtc::Thread* thread,
196 rtc::PacketSocketFactory* factory,
197 rtc::Network* network,
198 const rtc::IPAddress& ip,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200199 uint16_t min_port,
200 uint16_t max_port,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000201 const std::string& username,
202 const std::string& password,
203 const ProtocolAddress& server_address,
204 const RelayCredentials& credentials,
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000205 int server_priority,
206 const std::string& origin)
honghaizb19eba32015-08-03 10:23:31 -0700207 : Port(thread,
208 RELAY_PORT_TYPE,
209 factory,
210 network,
211 ip,
212 min_port,
213 max_port,
214 username,
215 password),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000216 server_address_(server_address),
217 credentials_(credentials),
218 socket_(NULL),
219 resolver_(NULL),
220 error_(0),
221 request_manager_(thread),
222 next_channel_number_(TURN_CHANNEL_NUMBER_START),
honghaizb19eba32015-08-03 10:23:31 -0700223 state_(STATE_CONNECTING),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000224 server_priority_(server_priority),
225 allocate_mismatch_retries_(0) {
226 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000227 request_manager_.set_origin(origin);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000228}
229
230TurnPort::~TurnPort() {
231 // TODO(juberti): Should this even be necessary?
pthatcher@webrtc.orgfe672e32015-01-17 00:58:15 +0000232
233 // release the allocation by sending a refresh with
234 // lifetime 0.
honghaizb19eba32015-08-03 10:23:31 -0700235 if (ready()) {
pthatcher@webrtc.orgfe672e32015-01-17 00:58:15 +0000236 TurnRefreshRequest bye(this);
237 bye.set_lifetime(0);
238 SendRequest(&bye, 0);
239 }
240
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000241 while (!entries_.empty()) {
242 DestroyEntry(entries_.front()->address());
243 }
244 if (resolver_) {
245 resolver_->Destroy(false);
246 }
247 if (!SharedSocket()) {
248 delete socket_;
249 }
250}
251
pthatcher@webrtc.org0ba15332015-01-10 00:47:02 +0000252rtc::SocketAddress TurnPort::GetLocalAddress() const {
253 return socket_ ? socket_->GetLocalAddress() : rtc::SocketAddress();
254}
255
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000256void TurnPort::PrepareAddress() {
257 if (credentials_.username.empty() ||
258 credentials_.password.empty()) {
259 LOG(LS_ERROR) << "Allocation can't be started without setting the"
260 << " TURN server credentials for the user.";
261 OnAllocateError();
262 return;
263 }
264
265 if (!server_address_.address.port()) {
266 // We will set default TURN port, if no port is set in the address.
267 server_address_.address.SetPort(TURN_DEFAULT_PORT);
268 }
269
270 if (server_address_.address.IsUnresolved()) {
271 ResolveTurnAddress(server_address_.address);
272 } else {
273 // If protocol family of server address doesn't match with local, return.
274 if (!IsCompatibleAddress(server_address_.address)) {
honghaizb19eba32015-08-03 10:23:31 -0700275 LOG(LS_ERROR) << "IP address family does not match: "
276 << "server: " << server_address_.address.family()
277 << "local: " << ip().family();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000278 OnAllocateError();
279 return;
280 }
281
282 // Insert the current address to prevent redirection pingpong.
283 attempted_server_addresses_.insert(server_address_.address);
284
285 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
286 << ProtoToString(server_address_.proto) << " @ "
287 << server_address_.address.ToSensitiveString();
288 if (!CreateTurnClientSocket()) {
honghaizb19eba32015-08-03 10:23:31 -0700289 LOG(LS_ERROR) << "Failed to create TURN client socket";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000290 OnAllocateError();
honghaizb19eba32015-08-03 10:23:31 -0700291 return;
292 }
293 if (server_address_.proto == PROTO_UDP) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000294 // If its UDP, send AllocateRequest now.
295 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
296 SendRequest(new TurnAllocateRequest(this), 0);
297 }
298 }
299}
300
301bool TurnPort::CreateTurnClientSocket() {
302 ASSERT(!socket_ || SharedSocket());
303
304 if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
305 socket_ = socket_factory()->CreateUdpSocket(
306 rtc::SocketAddress(ip(), 0), min_port(), max_port());
307 } else if (server_address_.proto == PROTO_TCP) {
308 ASSERT(!SharedSocket());
309 int opts = rtc::PacketSocketFactory::OPT_STUN;
310 // If secure bit is enabled in server address, use TLS over TCP.
311 if (server_address_.secure) {
312 opts |= rtc::PacketSocketFactory::OPT_TLS;
313 }
314 socket_ = socket_factory()->CreateClientTcpSocket(
315 rtc::SocketAddress(ip(), 0), server_address_.address,
316 proxy(), user_agent(), opts);
317 }
318
319 if (!socket_) {
320 error_ = SOCKET_ERROR;
321 return false;
322 }
323
324 // Apply options if any.
325 for (SocketOptionsMap::iterator iter = socket_options_.begin();
326 iter != socket_options_.end(); ++iter) {
327 socket_->SetOption(iter->first, iter->second);
328 }
329
330 if (!SharedSocket()) {
331 // If socket is shared, AllocationSequence will receive the packet.
332 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
333 }
334
335 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
336
honghaizb19eba32015-08-03 10:23:31 -0700337 // TCP port is ready to send stun requests after the socket is connected,
338 // while UDP port is ready to do so once the socket is created.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000339 if (server_address_.proto == PROTO_TCP) {
340 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
341 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
honghaizb19eba32015-08-03 10:23:31 -0700342 } else {
343 state_ = STATE_CONNECTED;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000344 }
345 return true;
346}
347
348void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
349 ASSERT(server_address_.proto == PROTO_TCP);
350 // Do not use this port if the socket bound to a different address than
351 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be
352 // given a binding address, and the platform is expected to pick the
353 // correct local address.
guoweis@webrtc.org4fba2932014-12-18 04:45:05 +0000354
Guo-wei Shieh7f04b082015-06-19 11:27:08 -0700355 // However, there are two situations in which we allow the bound address to
356 // differ from the requested address: 1. The bound address is the loopback
357 // address. This happens when a proxy forces TCP to bind to only the
358 // localhost address (see issue 3927). 2. The bound address is the "any
359 // address". This happens when multiple_routes is disabled (see issue 4780).
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000360 if (socket->GetLocalAddress().ipaddr() != ip()) {
guoweis@webrtc.org4fba2932014-12-18 04:45:05 +0000361 if (socket->GetLocalAddress().IsLoopbackIP()) {
362 LOG(LS_WARNING) << "Socket is bound to a different address:"
363 << socket->GetLocalAddress().ipaddr().ToString()
364 << ", rather then the local port:" << ip().ToString()
365 << ". Still allowing it since it's localhost.";
Guo-wei Shieh7f04b082015-06-19 11:27:08 -0700366 } else if (IPIsAny(ip())) {
367 LOG(LS_WARNING) << "Socket is bound to a different address:"
368 << socket->GetLocalAddress().ipaddr().ToString()
369 << ", rather then the local port:" << ip().ToString()
370 << ". Still allowing it since it's any address"
371 << ", possibly caused by multiple_routes being disabled.";
guoweis@webrtc.org4fba2932014-12-18 04:45:05 +0000372 } else {
373 LOG(LS_WARNING) << "Socket is bound to a different address:"
374 << socket->GetLocalAddress().ipaddr().ToString()
375 << ", rather then the local port:" << ip().ToString()
376 << ". Discarding TURN port.";
377 OnAllocateError();
378 return;
379 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000380 }
381
honghaizb19eba32015-08-03 10:23:31 -0700382 state_ = STATE_CONNECTED; // It is ready to send stun requests.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000383 if (server_address_.address.IsUnresolved()) {
384 server_address_.address = socket_->GetRemoteAddress();
385 }
386
387 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
388 << " using tcp.";
389 SendRequest(new TurnAllocateRequest(this), 0);
390}
391
392void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
393 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
guoweis@webrtc.org19e4e8d2015-01-10 02:41:32 +0000394 ASSERT(socket == socket_);
honghaizb19eba32015-08-03 10:23:31 -0700395 if (!ready()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000396 OnAllocateError();
397 }
honghaizb19eba32015-08-03 10:23:31 -0700398 request_manager_.Clear();
399 state_ = STATE_DISCONNECTED;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000400}
401
402void TurnPort::OnAllocateMismatch() {
403 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
404 LOG_J(LS_WARNING, this) << "Giving up on the port after "
405 << allocate_mismatch_retries_
406 << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
407 OnAllocateError();
408 return;
409 }
410
411 LOG_J(LS_INFO, this) << "Allocating a new socket after "
412 << "STUN_ERROR_ALLOCATION_MISMATCH, retry = "
413 << allocate_mismatch_retries_ + 1;
414 if (SharedSocket()) {
415 ResetSharedSocket();
416 } else {
417 delete socket_;
418 }
419 socket_ = NULL;
420
421 PrepareAddress();
422 ++allocate_mismatch_retries_;
423}
424
425Connection* TurnPort::CreateConnection(const Candidate& address,
426 CandidateOrigin origin) {
427 // TURN-UDP can only connect to UDP candidates.
428 if (address.protocol() != UDP_PROTOCOL_NAME) {
429 return NULL;
430 }
431
432 if (!IsCompatibleAddress(address.address())) {
433 return NULL;
434 }
435
honghaizb19eba32015-08-03 10:23:31 -0700436 if (state_ == STATE_DISCONNECTED) {
437 return NULL;
438 }
439
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000440 // Create an entry, if needed, so we can get our permissions set up correctly.
441 CreateEntry(address.address());
442
443 // A TURN port will have two candiates, STUN and TURN. STUN may not
444 // present in all cases. If present stun candidate will be added first
445 // and TURN candidate later.
446 for (size_t index = 0; index < Candidates().size(); ++index) {
447 if (Candidates()[index].type() == RELAY_PORT_TYPE) {
448 ProxyConnection* conn = new ProxyConnection(this, index, address);
449 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
450 AddConnection(conn);
451 return conn;
452 }
453 }
454 return NULL;
455}
456
457int TurnPort::SetOption(rtc::Socket::Option opt, int value) {
458 if (!socket_) {
459 // If socket is not created yet, these options will be applied during socket
460 // creation.
461 socket_options_[opt] = value;
462 return 0;
463 }
464 return socket_->SetOption(opt, value);
465}
466
467int TurnPort::GetOption(rtc::Socket::Option opt, int* value) {
468 if (!socket_) {
469 SocketOptionsMap::const_iterator it = socket_options_.find(opt);
470 if (it == socket_options_.end()) {
471 return -1;
472 }
473 *value = it->second;
474 return 0;
475 }
476
477 return socket_->GetOption(opt, value);
478}
479
480int TurnPort::GetError() {
481 return error_;
482}
483
484int TurnPort::SendTo(const void* data, size_t size,
485 const rtc::SocketAddress& addr,
486 const rtc::PacketOptions& options,
487 bool payload) {
488 // Try to find an entry for this specific address; we should have one.
489 TurnEntry* entry = FindEntry(addr);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000490 if (!entry) {
honghaizb19eba32015-08-03 10:23:31 -0700491 LOG(LS_ERROR) << "Did not find the TurnEntry for address " << addr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000492 return 0;
493 }
494
honghaizb19eba32015-08-03 10:23:31 -0700495 if (!ready()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000496 error_ = EWOULDBLOCK;
497 return SOCKET_ERROR;
498 }
499
500 // Send the actual contents to the server using the usual mechanism.
501 int sent = entry->Send(data, size, payload, options);
502 if (sent <= 0) {
503 return SOCKET_ERROR;
504 }
505
506 // The caller of the function is expecting the number of user data bytes,
507 // rather than the size of the packet.
508 return static_cast<int>(size);
509}
510
511void TurnPort::OnReadPacket(
512 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
513 const rtc::SocketAddress& remote_addr,
514 const rtc::PacketTime& packet_time) {
515 ASSERT(socket == socket_);
guoweis@webrtc.orgc51fb932014-12-18 00:30:55 +0000516
517 // This is to guard against a STUN response from previous server after
518 // alternative server redirection. TODO(guoweis): add a unit test for this
519 // race condition.
520 if (remote_addr != server_address_.address) {
521 LOG_J(LS_WARNING, this) << "Discarding TURN message from unknown address:"
522 << remote_addr.ToString()
523 << ", server_address_:"
524 << server_address_.address.ToString();
525 return;
526 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000527
528 // The message must be at least the size of a channel header.
529 if (size < TURN_CHANNEL_HEADER_SIZE) {
530 LOG_J(LS_WARNING, this) << "Received TURN message that was too short";
531 return;
532 }
533
534 // Check the message type, to see if is a Channel Data message.
535 // The message will either be channel data, a TURN data indication, or
536 // a response to a previous request.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200537 uint16_t msg_type = rtc::GetBE16(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000538 if (IsTurnChannelData(msg_type)) {
539 HandleChannelData(msg_type, data, size, packet_time);
540 } else if (msg_type == TURN_DATA_INDICATION) {
541 HandleDataIndication(data, size, packet_time);
542 } else {
jiayl@webrtc.org511f8a82014-12-03 02:17:07 +0000543 if (SharedSocket() &&
544 (msg_type == STUN_BINDING_RESPONSE ||
545 msg_type == STUN_BINDING_ERROR_RESPONSE)) {
546 LOG_J(LS_VERBOSE, this) <<
547 "Ignoring STUN binding response message on shared socket.";
548 return;
549 }
550
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000551 // This must be a response for one of our requests.
552 // Check success responses, but not errors, for MESSAGE-INTEGRITY.
553 if (IsStunSuccessResponseType(msg_type) &&
554 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
555 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
556 << "message integrity, msg_type=" << msg_type;
557 return;
558 }
559 request_manager_.CheckResponse(data, size);
560 }
561}
562
563void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
honghaizb19eba32015-08-03 10:23:31 -0700564 if (ready()) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000565 Port::OnReadyToSend();
566 }
567}
568
569
570// Update current server address port with the alternate server address port.
571bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
572 // Check if we have seen this address before and reject if we did.
573 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
574 if (iter != attempted_server_addresses_.end()) {
575 LOG_J(LS_WARNING, this) << "Redirection to ["
576 << address.ToSensitiveString()
577 << "] ignored, allocation failed.";
578 return false;
579 }
580
581 // If protocol family of server address doesn't match with local, return.
582 if (!IsCompatibleAddress(address)) {
583 LOG(LS_WARNING) << "Server IP address family does not match with "
584 << "local host address family type";
585 return false;
586 }
587
588 LOG_J(LS_INFO, this) << "Redirecting from TURN server ["
589 << server_address_.address.ToSensitiveString()
590 << "] to TURN server ["
591 << address.ToSensitiveString()
592 << "]";
593 server_address_ = ProtocolAddress(address, server_address_.proto,
594 server_address_.secure);
595
596 // Insert the current address to prevent redirection pingpong.
597 attempted_server_addresses_.insert(server_address_.address);
598 return true;
599}
600
601void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) {
602 if (resolver_)
603 return;
604
605 resolver_ = socket_factory()->CreateAsyncResolver();
606 resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
607 resolver_->Start(address);
608}
609
610void TurnPort::OnResolveResult(rtc::AsyncResolverInterface* resolver) {
611 ASSERT(resolver == resolver_);
612 // If DNS resolve is failed when trying to connect to the server using TCP,
613 // one of the reason could be due to DNS queries blocked by firewall.
614 // In such cases we will try to connect to the server with hostname, assuming
615 // socket layer will resolve the hostname through a HTTP proxy (if any).
616 if (resolver_->GetError() != 0 && server_address_.proto == PROTO_TCP) {
617 if (!CreateTurnClientSocket()) {
618 OnAllocateError();
619 }
620 return;
621 }
622
623 // Copy the original server address in |resolved_address|. For TLS based
624 // sockets we need hostname along with resolved address.
625 rtc::SocketAddress resolved_address = server_address_.address;
626 if (resolver_->GetError() != 0 ||
627 !resolver_->GetResolvedAddress(ip().family(), &resolved_address)) {
628 LOG_J(LS_WARNING, this) << "TURN host lookup received error "
629 << resolver_->GetError();
630 error_ = resolver_->GetError();
631 OnAllocateError();
632 return;
633 }
634 // Signal needs both resolved and unresolved address. After signal is sent
635 // we can copy resolved address back into |server_address_|.
636 SignalResolvedServerAddress(this, server_address_.address,
637 resolved_address);
638 server_address_.address = resolved_address;
639 PrepareAddress();
640}
641
642void TurnPort::OnSendStunPacket(const void* data, size_t size,
643 StunRequest* request) {
honghaizb19eba32015-08-03 10:23:31 -0700644 ASSERT(connected());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000645 rtc::PacketOptions options(DefaultDscpValue());
646 if (Send(data, size, options) < 0) {
647 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
648 << socket_->GetError();
649 }
650}
651
652void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
653 // STUN Port will discover STUN candidate, as it's supplied with first TURN
654 // server address.
655 // Why not using this address? - P2PTransportChannel will start creating
656 // connections after first candidate, which means it could start creating the
657 // connections before TURN candidate added. For that to handle, we need to
658 // supply STUN candidate from this port to UDPPort, and TurnPort should have
659 // handle to UDPPort to pass back the address.
660}
661
662void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
663 const rtc::SocketAddress& stun_address) {
honghaizb19eba32015-08-03 10:23:31 -0700664 state_ = STATE_READY;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000665
666 rtc::SocketAddress related_address = stun_address;
667 if (!(candidate_filter() & CF_REFLEXIVE)) {
668 // If candidate filter only allows relay type of address, empty raddr to
669 // avoid local address leakage.
670 related_address = rtc::EmptySocketAddressWithFamily(stun_address.family());
671 }
672
673 // For relayed candidate, Base is the candidate itself.
674 AddAddress(address, // Candidate address.
675 address, // Base address.
676 related_address, // Related address.
677 UDP_PROTOCOL_NAME,
Guo-wei Shieh3d564c12015-08-19 16:51:15 -0700678 ProtoToString(server_address_.proto), // The first hop protocol.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000679 "", // TCP canddiate type, empty for turn candidates.
680 RELAY_PORT_TYPE,
681 GetRelayPreference(server_address_.proto, server_address_.secure),
Guo-wei Shieh3d564c12015-08-19 16:51:15 -0700682 server_priority_, true);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000683}
684
685void TurnPort::OnAllocateError() {
686 // We will send SignalPortError asynchronously as this can be sent during
687 // port initialization. This way it will not be blocking other port
688 // creation.
689 thread()->Post(this, MSG_ERROR);
690}
691
692void TurnPort::OnMessage(rtc::Message* message) {
693 if (message->message_id == MSG_ERROR) {
694 SignalPortError(this);
695 return;
696 } else if (message->message_id == MSG_ALLOCATE_MISMATCH) {
697 OnAllocateMismatch();
698 return;
guoweis@webrtc.org19e4e8d2015-01-10 02:41:32 +0000699 } else if (message->message_id == MSG_TRY_ALTERNATE_SERVER) {
700 if (server_address().proto == PROTO_UDP) {
701 // Send another allocate request to alternate server, with the received
702 // realm and nonce values.
703 SendRequest(new TurnAllocateRequest(this), 0);
704 } else {
705 // Since it's TCP, we have to delete the connected socket and reconnect
706 // with the alternate server. PrepareAddress will send stun binding once
707 // the new socket is connected.
708 ASSERT(server_address().proto == PROTO_TCP);
709 ASSERT(!SharedSocket());
710 delete socket_;
711 socket_ = NULL;
712 PrepareAddress();
713 }
714 return;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000715 }
716
717 Port::OnMessage(message);
718}
719
720void TurnPort::OnAllocateRequestTimeout() {
721 OnAllocateError();
722}
723
724void TurnPort::HandleDataIndication(const char* data, size_t size,
725 const rtc::PacketTime& packet_time) {
726 // Read in the message, and process according to RFC5766, Section 10.4.
727 rtc::ByteBuffer buf(data, size);
728 TurnMessage msg;
729 if (!msg.Read(&buf)) {
730 LOG_J(LS_WARNING, this) << "Received invalid TURN data indication";
731 return;
732 }
733
734 // Check mandatory attributes.
735 const StunAddressAttribute* addr_attr =
736 msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
737 if (!addr_attr) {
738 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
739 << "in data indication.";
740 return;
741 }
742
743 const StunByteStringAttribute* data_attr =
744 msg.GetByteString(STUN_ATTR_DATA);
745 if (!data_attr) {
746 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_DATA attribute in "
747 << "data indication.";
748 return;
749 }
750
751 // Verify that the data came from somewhere we think we have a permission for.
752 rtc::SocketAddress ext_addr(addr_attr->GetAddress());
753 if (!HasPermission(ext_addr.ipaddr())) {
754 LOG_J(LS_WARNING, this) << "Received TURN data indication with invalid "
755 << "peer address, addr="
756 << ext_addr.ToSensitiveString();
757 return;
758 }
759
760 DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr,
761 PROTO_UDP, packet_time);
762}
763
764void TurnPort::HandleChannelData(int channel_id, const char* data,
765 size_t size,
766 const rtc::PacketTime& packet_time) {
767 // Read the message, and process according to RFC5766, Section 11.6.
768 // 0 1 2 3
769 // 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
770 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
771 // | Channel Number | Length |
772 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
773 // | |
774 // / Application Data /
775 // / /
776 // | |
777 // | +-------------------------------+
778 // | |
779 // +-------------------------------+
780
781 // Extract header fields from the message.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200782 uint16_t len = rtc::GetBE16(data + 2);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000783 if (len > size - TURN_CHANNEL_HEADER_SIZE) {
784 LOG_J(LS_WARNING, this) << "Received TURN channel data message with "
785 << "incorrect length, len=" << len;
786 return;
787 }
788 // Allowing messages larger than |len|, as ChannelData can be padded.
789
790 TurnEntry* entry = FindEntry(channel_id);
791 if (!entry) {
792 LOG_J(LS_WARNING, this) << "Received TURN channel data message for invalid "
793 << "channel, channel_id=" << channel_id;
794 return;
795 }
796
797 DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
798 PROTO_UDP, packet_time);
799}
800
801void TurnPort::DispatchPacket(const char* data, size_t size,
802 const rtc::SocketAddress& remote_addr,
803 ProtocolType proto, const rtc::PacketTime& packet_time) {
804 if (Connection* conn = GetConnection(remote_addr)) {
805 conn->OnReadPacket(data, size, packet_time);
806 } else {
807 Port::OnReadPacket(data, size, remote_addr, proto);
808 }
809}
810
811bool TurnPort::ScheduleRefresh(int lifetime) {
812 // Lifetime is in seconds; we schedule a refresh for one minute less.
813 if (lifetime < 2 * 60) {
814 LOG_J(LS_WARNING, this) << "Received response with lifetime that was "
815 << "too short, lifetime=" << lifetime;
816 return false;
817 }
818
Peter Thatcherb32a5c42015-04-10 14:04:42 -0700819 int delay = (lifetime - 60) * 1000;
820 SendRequest(new TurnRefreshRequest(this), delay);
821 LOG_J(LS_INFO, this) << "Scheduled refresh in " << delay << "ms.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000822 return true;
823}
824
825void TurnPort::SendRequest(StunRequest* req, int delay) {
826 request_manager_.SendDelayed(req, delay);
827}
828
829void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
830 // If we've gotten the necessary data from the server, add it to our request.
831 VERIFY(!hash_.empty());
832 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
833 STUN_ATTR_USERNAME, credentials_.username)));
834 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
835 STUN_ATTR_REALM, realm_)));
836 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
837 STUN_ATTR_NONCE, nonce_)));
838 VERIFY(msg->AddMessageIntegrity(hash()));
839}
840
841int TurnPort::Send(const void* data, size_t len,
842 const rtc::PacketOptions& options) {
843 return socket_->SendTo(data, len, server_address_.address, options);
844}
845
846void TurnPort::UpdateHash() {
847 VERIFY(ComputeStunCredentialHash(credentials_.username, realm_,
848 credentials_.password, &hash_));
849}
850
851bool TurnPort::UpdateNonce(StunMessage* response) {
852 // When stale nonce error received, we should update
853 // hash and store realm and nonce.
854 // Check the mandatory attributes.
855 const StunByteStringAttribute* realm_attr =
856 response->GetByteString(STUN_ATTR_REALM);
857 if (!realm_attr) {
858 LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
859 << "stale nonce error response.";
860 return false;
861 }
862 set_realm(realm_attr->GetString());
863
864 const StunByteStringAttribute* nonce_attr =
865 response->GetByteString(STUN_ATTR_NONCE);
866 if (!nonce_attr) {
867 LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
868 << "stale nonce error response.";
869 return false;
870 }
871 set_nonce(nonce_attr->GetString());
872 return true;
873}
874
875static bool MatchesIP(TurnEntry* e, rtc::IPAddress ipaddr) {
876 return e->address().ipaddr() == ipaddr;
877}
878bool TurnPort::HasPermission(const rtc::IPAddress& ipaddr) const {
879 return (std::find_if(entries_.begin(), entries_.end(),
880 std::bind2nd(std::ptr_fun(MatchesIP), ipaddr)) != entries_.end());
881}
882
883static bool MatchesAddress(TurnEntry* e, rtc::SocketAddress addr) {
884 return e->address() == addr;
885}
886TurnEntry* TurnPort::FindEntry(const rtc::SocketAddress& addr) const {
887 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
888 std::bind2nd(std::ptr_fun(MatchesAddress), addr));
889 return (it != entries_.end()) ? *it : NULL;
890}
891
892static bool MatchesChannelId(TurnEntry* e, int id) {
893 return e->channel_id() == id;
894}
895TurnEntry* TurnPort::FindEntry(int channel_id) const {
896 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
897 std::bind2nd(std::ptr_fun(MatchesChannelId), channel_id));
898 return (it != entries_.end()) ? *it : NULL;
899}
900
901TurnEntry* TurnPort::CreateEntry(const rtc::SocketAddress& addr) {
902 ASSERT(FindEntry(addr) == NULL);
903 TurnEntry* entry = new TurnEntry(this, next_channel_number_++, addr);
904 entries_.push_back(entry);
905 return entry;
906}
907
908void TurnPort::DestroyEntry(const rtc::SocketAddress& addr) {
909 TurnEntry* entry = FindEntry(addr);
910 ASSERT(entry != NULL);
911 entry->SignalDestroyed(entry);
912 entries_.remove(entry);
913 delete entry;
914}
915
916void TurnPort::OnConnectionDestroyed(Connection* conn) {
917 // Destroying TurnEntry for the connection, which is already destroyed.
918 DestroyEntry(conn->remote_candidate().address());
919}
920
921TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
922 : StunRequest(new TurnMessage()),
923 port_(port) {
924}
925
926void TurnAllocateRequest::Prepare(StunMessage* request) {
927 // Create the request as indicated in RFC 5766, Section 6.1.
928 request->SetType(TURN_ALLOCATE_REQUEST);
929 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
930 STUN_ATTR_REQUESTED_TRANSPORT);
931 transport_attr->SetValue(IPPROTO_UDP << 24);
932 VERIFY(request->AddAttribute(transport_attr));
933 if (!port_->hash().empty()) {
934 port_->AddRequestAuthInfo(request);
935 }
936}
937
Peter Thatcher1cf6f812015-05-15 10:40:45 -0700938void TurnAllocateRequest::OnSent() {
939 LOG_J(LS_INFO, port_) << "TURN allocate request sent"
940 << ", id=" << rtc::hex_encode(id());
941 StunRequest::OnSent();
942}
943
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000944void TurnAllocateRequest::OnResponse(StunMessage* response) {
Peter Thatcher1cf6f812015-05-15 10:40:45 -0700945 LOG_J(LS_INFO, port_) << "TURN allocate requested successfully"
946 << ", id=" << rtc::hex_encode(id())
947 << ", code=0" // Makes logging easier to parse.
948 << ", rtt=" << Elapsed();
949
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000950 // Check mandatory attributes as indicated in RFC5766, Section 6.3.
951 const StunAddressAttribute* mapped_attr =
952 response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
953 if (!mapped_attr) {
954 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
955 << "attribute in allocate success response";
956 return;
957 }
958 // Using XOR-Mapped-Address for stun.
959 port_->OnStunAddress(mapped_attr->GetAddress());
960
961 const StunAddressAttribute* relayed_attr =
962 response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
963 if (!relayed_attr) {
964 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
965 << "attribute in allocate success response";
966 return;
967 }
968
969 const StunUInt32Attribute* lifetime_attr =
970 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
971 if (!lifetime_attr) {
972 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
973 << "allocate success response";
974 return;
975 }
976 // Notify the port the allocate succeeded, and schedule a refresh request.
977 port_->OnAllocateSuccess(relayed_attr->GetAddress(),
978 mapped_attr->GetAddress());
979 port_->ScheduleRefresh(lifetime_attr->value());
980}
981
982void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
983 // Process error response according to RFC5766, Section 6.4.
984 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
Peter Thatcher1cf6f812015-05-15 10:40:45 -0700985
986 LOG_J(LS_INFO, port_) << "Received TURN allocate error response"
987 << ", id=" << rtc::hex_encode(id())
988 << ", code=" << error_code->code()
989 << ", rtt=" << Elapsed();
990
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000991 switch (error_code->code()) {
992 case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
993 OnAuthChallenge(response, error_code->code());
994 break;
995 case STUN_ERROR_TRY_ALTERNATE:
996 OnTryAlternate(response, error_code->code());
997 break;
998 case STUN_ERROR_ALLOCATION_MISMATCH:
999 // We must handle this error async because trying to delete the socket in
1000 // OnErrorResponse will cause a deadlock on the socket.
1001 port_->thread()->Post(port_, TurnPort::MSG_ALLOCATE_MISMATCH);
1002 break;
1003 default:
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001004 LOG_J(LS_WARNING, port_) << "Received TURN allocate error response"
1005 << ", id=" << rtc::hex_encode(id())
1006 << ", code=" << error_code->code()
1007 << ", rtt=" << Elapsed();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001008 port_->OnAllocateError();
1009 }
1010}
1011
1012void TurnAllocateRequest::OnTimeout() {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001013 LOG_J(LS_WARNING, port_) << "TURN allocate request "
1014 << rtc::hex_encode(id()) << " timout";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001015 port_->OnAllocateRequestTimeout();
1016}
1017
1018void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
1019 // If we failed to authenticate even after we sent our credentials, fail hard.
1020 if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
1021 LOG_J(LS_WARNING, port_) << "Failed to authenticate with the server "
1022 << "after challenge.";
1023 port_->OnAllocateError();
1024 return;
1025 }
1026
1027 // Check the mandatory attributes.
1028 const StunByteStringAttribute* realm_attr =
1029 response->GetByteString(STUN_ATTR_REALM);
1030 if (!realm_attr) {
1031 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_REALM attribute in "
1032 << "allocate unauthorized response.";
1033 return;
1034 }
1035 port_->set_realm(realm_attr->GetString());
1036
1037 const StunByteStringAttribute* nonce_attr =
1038 response->GetByteString(STUN_ATTR_NONCE);
1039 if (!nonce_attr) {
1040 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_NONCE attribute in "
1041 << "allocate unauthorized response.";
1042 return;
1043 }
1044 port_->set_nonce(nonce_attr->GetString());
1045
1046 // Send another allocate request, with the received realm and nonce values.
1047 port_->SendRequest(new TurnAllocateRequest(port_), 0);
1048}
1049
1050void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001051
1052 // According to RFC 5389 section 11, there are use cases where
1053 // authentication of response is not possible, we're not validating
1054 // message integrity.
1055
1056 // Get the alternate server address attribute value.
1057 const StunAddressAttribute* alternate_server_attr =
1058 response->GetAddress(STUN_ATTR_ALTERNATE_SERVER);
1059 if (!alternate_server_attr) {
1060 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_ALTERNATE_SERVER "
1061 << "attribute in try alternate error response";
1062 port_->OnAllocateError();
1063 return;
1064 }
1065 if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) {
1066 port_->OnAllocateError();
1067 return;
1068 }
1069
1070 // Check the attributes.
1071 const StunByteStringAttribute* realm_attr =
1072 response->GetByteString(STUN_ATTR_REALM);
1073 if (realm_attr) {
1074 LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_REALM attribute in "
1075 << "try alternate error response.";
1076 port_->set_realm(realm_attr->GetString());
1077 }
1078
1079 const StunByteStringAttribute* nonce_attr =
1080 response->GetByteString(STUN_ATTR_NONCE);
1081 if (nonce_attr) {
1082 LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_NONCE attribute in "
1083 << "try alternate error response.";
1084 port_->set_nonce(nonce_attr->GetString());
1085 }
1086
guoweis@webrtc.org19e4e8d2015-01-10 02:41:32 +00001087 // For TCP, we can't close the original Tcp socket during handling a 300 as
1088 // we're still inside that socket's event handler. Doing so will cause
1089 // deadlock.
1090 port_->thread()->Post(port_, TurnPort::MSG_TRY_ALTERNATE_SERVER);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001091}
1092
1093TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
1094 : StunRequest(new TurnMessage()),
pthatcher@webrtc.orgfe672e32015-01-17 00:58:15 +00001095 port_(port),
1096 lifetime_(-1) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001097}
1098
1099void TurnRefreshRequest::Prepare(StunMessage* request) {
1100 // Create the request as indicated in RFC 5766, Section 7.1.
1101 // No attributes need to be included.
1102 request->SetType(TURN_REFRESH_REQUEST);
pthatcher@webrtc.orgfe672e32015-01-17 00:58:15 +00001103 if (lifetime_ > -1) {
1104 VERIFY(request->AddAttribute(new StunUInt32Attribute(
1105 STUN_ATTR_LIFETIME, lifetime_)));
1106 }
1107
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001108 port_->AddRequestAuthInfo(request);
1109}
1110
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001111void TurnRefreshRequest::OnSent() {
1112 LOG_J(LS_INFO, port_) << "TURN refresh request sent"
1113 << ", id=" << rtc::hex_encode(id());
1114 StunRequest::OnSent();
1115}
1116
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001117void TurnRefreshRequest::OnResponse(StunMessage* response) {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001118 LOG_J(LS_INFO, port_) << "TURN refresh requested successfully"
1119 << ", id=" << rtc::hex_encode(id())
1120 << ", code=0" // Makes logging easier to parse.
1121 << ", rtt=" << Elapsed();
Peter Thatcherb32a5c42015-04-10 14:04:42 -07001122
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001123 // Check mandatory attributes as indicated in RFC5766, Section 7.3.
1124 const StunUInt32Attribute* lifetime_attr =
1125 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
1126 if (!lifetime_attr) {
1127 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
1128 << "refresh success response.";
1129 return;
1130 }
1131
1132 // Schedule a refresh based on the returned lifetime value.
1133 port_->ScheduleRefresh(lifetime_attr->value());
1134}
1135
1136void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
1137 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001138
1139 LOG_J(LS_INFO, port_) << "Received TURN refresh error response"
1140 << ", id=" << rtc::hex_encode(id())
1141 << ", code=" << error_code->code()
1142 << ", rtt=" << Elapsed();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001143
1144 if (error_code->code() == STUN_ERROR_STALE_NONCE) {
1145 if (port_->UpdateNonce(response)) {
1146 // Send RefreshRequest immediately.
1147 port_->SendRequest(new TurnRefreshRequest(port_), 0);
1148 }
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001149 } else {
1150 LOG_J(LS_WARNING, port_) << "Received TURN refresh error response"
1151 << ", id=" << rtc::hex_encode(id())
1152 << ", code=" << error_code->code()
1153 << ", rtt=" << Elapsed();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001154 }
1155}
1156
1157void TurnRefreshRequest::OnTimeout() {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001158 LOG_J(LS_WARNING, port_) << "TURN refresh timeout " << rtc::hex_encode(id());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001159}
1160
1161TurnCreatePermissionRequest::TurnCreatePermissionRequest(
1162 TurnPort* port, TurnEntry* entry,
1163 const rtc::SocketAddress& ext_addr)
1164 : StunRequest(new TurnMessage()),
1165 port_(port),
1166 entry_(entry),
1167 ext_addr_(ext_addr) {
1168 entry_->SignalDestroyed.connect(
1169 this, &TurnCreatePermissionRequest::OnEntryDestroyed);
1170}
1171
1172void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
1173 // Create the request as indicated in RFC5766, Section 9.1.
1174 request->SetType(TURN_CREATE_PERMISSION_REQUEST);
1175 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
1176 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1177 port_->AddRequestAuthInfo(request);
1178}
1179
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001180void TurnCreatePermissionRequest::OnSent() {
1181 LOG_J(LS_INFO, port_) << "TURN create permission request sent"
1182 << ", id=" << rtc::hex_encode(id());
1183 StunRequest::OnSent();
1184}
1185
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001186void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001187 LOG_J(LS_INFO, port_) << "TURN permission requested successfully"
1188 << ", id=" << rtc::hex_encode(id())
1189 << ", code=0" // Makes logging easier to parse.
1190 << ", rtt=" << Elapsed();
1191
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001192 if (entry_) {
1193 entry_->OnCreatePermissionSuccess();
1194 }
1195}
1196
1197void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
Peter Thatcherb32a5c42015-04-10 14:04:42 -07001198 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001199 LOG_J(LS_WARNING, port_) << "Received TURN create permission error response"
1200 << ", id=" << rtc::hex_encode(id())
1201 << ", code=" << error_code->code()
1202 << ", rtt=" << Elapsed();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001203 if (entry_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001204 entry_->OnCreatePermissionError(response, error_code->code());
1205 }
1206}
1207
1208void TurnCreatePermissionRequest::OnTimeout() {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001209 LOG_J(LS_WARNING, port_) << "TURN create permission timeout "
1210 << rtc::hex_encode(id());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001211}
1212
1213void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
1214 ASSERT(entry_ == entry);
1215 entry_ = NULL;
1216}
1217
1218TurnChannelBindRequest::TurnChannelBindRequest(
1219 TurnPort* port, TurnEntry* entry,
1220 int channel_id, const rtc::SocketAddress& ext_addr)
1221 : StunRequest(new TurnMessage()),
1222 port_(port),
1223 entry_(entry),
1224 channel_id_(channel_id),
1225 ext_addr_(ext_addr) {
1226 entry_->SignalDestroyed.connect(
1227 this, &TurnChannelBindRequest::OnEntryDestroyed);
1228}
1229
1230void TurnChannelBindRequest::Prepare(StunMessage* request) {
1231 // Create the request as indicated in RFC5766, Section 11.1.
1232 request->SetType(TURN_CHANNEL_BIND_REQUEST);
1233 VERIFY(request->AddAttribute(new StunUInt32Attribute(
1234 STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16)));
1235 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
1236 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1237 port_->AddRequestAuthInfo(request);
1238}
1239
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001240void TurnChannelBindRequest::OnSent() {
1241 LOG_J(LS_INFO, port_) << "TURN channel bind request sent"
1242 << ", id=" << rtc::hex_encode(id());
1243 StunRequest::OnSent();
1244}
1245
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001246void TurnChannelBindRequest::OnResponse(StunMessage* response) {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001247 LOG_J(LS_INFO, port_) << "TURN channel bind requested successfully"
1248 << ", id=" << rtc::hex_encode(id())
1249 << ", code=0" // Makes logging easier to parse.
1250 << ", rtt=" << Elapsed();
1251
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001252 if (entry_) {
1253 entry_->OnChannelBindSuccess();
1254 // Refresh the channel binding just under the permission timeout
1255 // threshold. The channel binding has a longer lifetime, but
1256 // this is the easiest way to keep both the channel and the
1257 // permission from expiring.
Peter Thatcherb32a5c42015-04-10 14:04:42 -07001258 int delay = TURN_PERMISSION_TIMEOUT - 60000;
1259 entry_->SendChannelBindRequest(delay);
1260 LOG_J(LS_INFO, port_) << "Scheduled channel bind in " << delay << "ms.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001261 }
1262}
1263
1264void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001265 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1266 LOG_J(LS_WARNING, port_) << "Received TURN channel bind error response"
1267 << ", id=" << rtc::hex_encode(id())
1268 << ", code=" << error_code->code()
1269 << ", rtt=" << Elapsed();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001270 if (entry_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001271 entry_->OnChannelBindError(response, error_code->code());
1272 }
1273}
1274
1275void TurnChannelBindRequest::OnTimeout() {
Peter Thatcher1cf6f812015-05-15 10:40:45 -07001276 LOG_J(LS_WARNING, port_) << "TURN channel bind timeout "
1277 << rtc::hex_encode(id());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001278}
1279
1280void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
1281 ASSERT(entry_ == entry);
1282 entry_ = NULL;
1283}
1284
1285TurnEntry::TurnEntry(TurnPort* port, int channel_id,
1286 const rtc::SocketAddress& ext_addr)
1287 : port_(port),
1288 channel_id_(channel_id),
1289 ext_addr_(ext_addr),
1290 state_(STATE_UNBOUND) {
1291 // Creating permission for |ext_addr_|.
1292 SendCreatePermissionRequest();
1293}
1294
1295void TurnEntry::SendCreatePermissionRequest() {
1296 port_->SendRequest(new TurnCreatePermissionRequest(
1297 port_, this, ext_addr_), 0);
1298}
1299
1300void TurnEntry::SendChannelBindRequest(int delay) {
1301 port_->SendRequest(new TurnChannelBindRequest(
1302 port_, this, channel_id_, ext_addr_), delay);
1303}
1304
1305int TurnEntry::Send(const void* data, size_t size, bool payload,
1306 const rtc::PacketOptions& options) {
1307 rtc::ByteBuffer buf;
1308 if (state_ != STATE_BOUND) {
1309 // If we haven't bound the channel yet, we have to use a Send Indication.
1310 TurnMessage msg;
1311 msg.SetType(TURN_SEND_INDICATION);
1312 msg.SetTransactionID(
1313 rtc::CreateRandomString(kStunTransactionIdLength));
1314 VERIFY(msg.AddAttribute(new StunXorAddressAttribute(
1315 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1316 VERIFY(msg.AddAttribute(new StunByteStringAttribute(
1317 STUN_ATTR_DATA, data, size)));
1318 VERIFY(msg.Write(&buf));
1319
1320 // If we're sending real data, request a channel bind that we can use later.
1321 if (state_ == STATE_UNBOUND && payload) {
1322 SendChannelBindRequest(0);
1323 state_ = STATE_BINDING;
1324 }
1325 } else {
1326 // If the channel is bound, we can send the data as a Channel Message.
1327 buf.WriteUInt16(channel_id_);
Peter Boström0c4e06b2015-10-07 12:23:21 +02001328 buf.WriteUInt16(static_cast<uint16_t>(size));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001329 buf.WriteBytes(reinterpret_cast<const char*>(data), size);
1330 }
1331 return port_->Send(buf.Data(), buf.Length(), options);
1332}
1333
1334void TurnEntry::OnCreatePermissionSuccess() {
1335 LOG_J(LS_INFO, port_) << "Create permission for "
1336 << ext_addr_.ToSensitiveString()
1337 << " succeeded";
1338 // For success result code will be 0.
1339 port_->SignalCreatePermissionResult(port_, ext_addr_, 0);
1340}
1341
1342void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001343 if (code == STUN_ERROR_STALE_NONCE) {
1344 if (port_->UpdateNonce(response)) {
1345 SendCreatePermissionRequest();
1346 }
1347 } else {
1348 // Send signal with error code.
1349 port_->SignalCreatePermissionResult(port_, ext_addr_, code);
1350 }
1351}
1352
1353void TurnEntry::OnChannelBindSuccess() {
1354 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString()
1355 << " succeeded";
1356 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND);
1357 state_ = STATE_BOUND;
1358}
1359
1360void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1361 // TODO(mallinath) - Implement handling of error response for channel
1362 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001363 if (code == STUN_ERROR_STALE_NONCE) {
1364 if (port_->UpdateNonce(response)) {
1365 // Send channel bind request with fresh nonce.
1366 SendChannelBindRequest(0);
1367 }
1368 }
1369}
1370
1371} // namespace cricket