blob: e7626fe04c880765df3e013b2acca92cd1392f26 [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
41inline bool IsTurnChannelData(uint16 msg_type) {
42 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);
60 virtual void Prepare(StunMessage* request);
61 virtual void OnResponse(StunMessage* response);
62 virtual void OnErrorResponse(StunMessage* response);
63 virtual void OnTimeout();
64
65 private:
66 // Handles authentication challenge from the server.
67 void OnAuthChallenge(StunMessage* response, int code);
68 void OnTryAlternate(StunMessage* response, int code);
69 void OnUnknownAttribute(StunMessage* response);
70
71 TurnPort* port_;
72};
73
74class TurnRefreshRequest : public StunRequest {
75 public:
76 explicit TurnRefreshRequest(TurnPort* port);
77 virtual void Prepare(StunMessage* request);
78 virtual void OnResponse(StunMessage* response);
79 virtual void OnErrorResponse(StunMessage* response);
80 virtual void OnTimeout();
81
82 private:
83 TurnPort* port_;
84};
85
86class TurnCreatePermissionRequest : public StunRequest,
87 public sigslot::has_slots<> {
88 public:
89 TurnCreatePermissionRequest(TurnPort* port, TurnEntry* entry,
90 const rtc::SocketAddress& ext_addr);
91 virtual void Prepare(StunMessage* request);
92 virtual void OnResponse(StunMessage* response);
93 virtual void OnErrorResponse(StunMessage* response);
94 virtual void OnTimeout();
95
96 private:
97 void OnEntryDestroyed(TurnEntry* entry);
98
99 TurnPort* port_;
100 TurnEntry* entry_;
101 rtc::SocketAddress ext_addr_;
102};
103
104class TurnChannelBindRequest : public StunRequest,
105 public sigslot::has_slots<> {
106 public:
107 TurnChannelBindRequest(TurnPort* port, TurnEntry* entry, int channel_id,
108 const rtc::SocketAddress& ext_addr);
109 virtual void Prepare(StunMessage* request);
110 virtual void OnResponse(StunMessage* response);
111 virtual void OnErrorResponse(StunMessage* response);
112 virtual void OnTimeout();
113
114 private:
115 void OnEntryDestroyed(TurnEntry* entry);
116
117 TurnPort* port_;
118 TurnEntry* entry_;
119 int channel_id_;
120 rtc::SocketAddress ext_addr_;
121};
122
123// Manages a "connection" to a remote destination. We will attempt to bring up
124// a channel for this remote destination to reduce the overhead of sending data.
125class TurnEntry : public sigslot::has_slots<> {
126 public:
127 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
128 TurnEntry(TurnPort* port, int channel_id,
129 const rtc::SocketAddress& ext_addr);
130
131 TurnPort* port() { return port_; }
132
133 int channel_id() const { return channel_id_; }
134 const rtc::SocketAddress& address() const { return ext_addr_; }
135 BindState state() const { return state_; }
136
137 // Helper methods to send permission and channel bind requests.
138 void SendCreatePermissionRequest();
139 void SendChannelBindRequest(int delay);
140 // Sends a packet to the given destination address.
141 // This will wrap the packet in STUN if necessary.
142 int Send(const void* data, size_t size, bool payload,
143 const rtc::PacketOptions& options);
144
145 void OnCreatePermissionSuccess();
146 void OnCreatePermissionError(StunMessage* response, int code);
147 void OnChannelBindSuccess();
148 void OnChannelBindError(StunMessage* response, int code);
149 // Signal sent when TurnEntry is destroyed.
150 sigslot::signal1<TurnEntry*> SignalDestroyed;
151
152 private:
153 TurnPort* port_;
154 int channel_id_;
155 rtc::SocketAddress ext_addr_;
156 BindState state_;
157};
158
159TurnPort::TurnPort(rtc::Thread* thread,
160 rtc::PacketSocketFactory* factory,
161 rtc::Network* network,
162 rtc::AsyncPacketSocket* socket,
163 const std::string& username,
164 const std::string& password,
165 const ProtocolAddress& server_address,
166 const RelayCredentials& credentials,
167 int server_priority)
168 : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
169 username, password),
170 server_address_(server_address),
171 credentials_(credentials),
172 socket_(socket),
173 resolver_(NULL),
174 error_(0),
175 request_manager_(thread),
176 next_channel_number_(TURN_CHANNEL_NUMBER_START),
177 connected_(false),
178 server_priority_(server_priority),
179 allocate_mismatch_retries_(0) {
180 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
181}
182
183TurnPort::TurnPort(rtc::Thread* thread,
184 rtc::PacketSocketFactory* factory,
185 rtc::Network* network,
186 const rtc::IPAddress& ip,
187 int min_port, int max_port,
188 const std::string& username,
189 const std::string& password,
190 const ProtocolAddress& server_address,
191 const RelayCredentials& credentials,
192 int server_priority)
193 : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port,
194 username, password),
195 server_address_(server_address),
196 credentials_(credentials),
197 socket_(NULL),
198 resolver_(NULL),
199 error_(0),
200 request_manager_(thread),
201 next_channel_number_(TURN_CHANNEL_NUMBER_START),
202 connected_(false),
203 server_priority_(server_priority),
204 allocate_mismatch_retries_(0) {
205 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
206}
207
208TurnPort::~TurnPort() {
209 // TODO(juberti): Should this even be necessary?
210 while (!entries_.empty()) {
211 DestroyEntry(entries_.front()->address());
212 }
213 if (resolver_) {
214 resolver_->Destroy(false);
215 }
216 if (!SharedSocket()) {
217 delete socket_;
218 }
219}
220
221void TurnPort::PrepareAddress() {
222 if (credentials_.username.empty() ||
223 credentials_.password.empty()) {
224 LOG(LS_ERROR) << "Allocation can't be started without setting the"
225 << " TURN server credentials for the user.";
226 OnAllocateError();
227 return;
228 }
229
230 if (!server_address_.address.port()) {
231 // We will set default TURN port, if no port is set in the address.
232 server_address_.address.SetPort(TURN_DEFAULT_PORT);
233 }
234
235 if (server_address_.address.IsUnresolved()) {
236 ResolveTurnAddress(server_address_.address);
237 } else {
238 // If protocol family of server address doesn't match with local, return.
239 if (!IsCompatibleAddress(server_address_.address)) {
240 LOG(LS_ERROR) << "Server IP address family does not match with "
241 << "local host address family type";
242 OnAllocateError();
243 return;
244 }
245
246 // Insert the current address to prevent redirection pingpong.
247 attempted_server_addresses_.insert(server_address_.address);
248
249 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
250 << ProtoToString(server_address_.proto) << " @ "
251 << server_address_.address.ToSensitiveString();
252 if (!CreateTurnClientSocket()) {
253 OnAllocateError();
254 } else if (server_address_.proto == PROTO_UDP) {
255 // If its UDP, send AllocateRequest now.
256 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
257 SendRequest(new TurnAllocateRequest(this), 0);
258 }
259 }
260}
261
262bool TurnPort::CreateTurnClientSocket() {
263 ASSERT(!socket_ || SharedSocket());
264
265 if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
266 socket_ = socket_factory()->CreateUdpSocket(
267 rtc::SocketAddress(ip(), 0), min_port(), max_port());
268 } else if (server_address_.proto == PROTO_TCP) {
269 ASSERT(!SharedSocket());
270 int opts = rtc::PacketSocketFactory::OPT_STUN;
271 // If secure bit is enabled in server address, use TLS over TCP.
272 if (server_address_.secure) {
273 opts |= rtc::PacketSocketFactory::OPT_TLS;
274 }
275 socket_ = socket_factory()->CreateClientTcpSocket(
276 rtc::SocketAddress(ip(), 0), server_address_.address,
277 proxy(), user_agent(), opts);
278 }
279
280 if (!socket_) {
281 error_ = SOCKET_ERROR;
282 return false;
283 }
284
285 // Apply options if any.
286 for (SocketOptionsMap::iterator iter = socket_options_.begin();
287 iter != socket_options_.end(); ++iter) {
288 socket_->SetOption(iter->first, iter->second);
289 }
290
291 if (!SharedSocket()) {
292 // If socket is shared, AllocationSequence will receive the packet.
293 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
294 }
295
296 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
297
298 if (server_address_.proto == PROTO_TCP) {
299 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
300 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
301 }
302 return true;
303}
304
305void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
306 ASSERT(server_address_.proto == PROTO_TCP);
307 // Do not use this port if the socket bound to a different address than
308 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be
309 // given a binding address, and the platform is expected to pick the
310 // correct local address.
311 if (socket->GetLocalAddress().ipaddr() != ip()) {
312 LOG(LS_WARNING) << "Socket is bound to a different address then the "
313 << "local port. Discarding TURN port.";
314 OnAllocateError();
315 return;
316 }
317
318 if (server_address_.address.IsUnresolved()) {
319 server_address_.address = socket_->GetRemoteAddress();
320 }
321
322 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
323 << " using tcp.";
324 SendRequest(new TurnAllocateRequest(this), 0);
325}
326
327void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
328 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
329 if (!connected_) {
330 OnAllocateError();
331 }
332}
333
334void TurnPort::OnAllocateMismatch() {
335 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
336 LOG_J(LS_WARNING, this) << "Giving up on the port after "
337 << allocate_mismatch_retries_
338 << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
339 OnAllocateError();
340 return;
341 }
342
343 LOG_J(LS_INFO, this) << "Allocating a new socket after "
344 << "STUN_ERROR_ALLOCATION_MISMATCH, retry = "
345 << allocate_mismatch_retries_ + 1;
346 if (SharedSocket()) {
347 ResetSharedSocket();
348 } else {
349 delete socket_;
350 }
351 socket_ = NULL;
352
353 PrepareAddress();
354 ++allocate_mismatch_retries_;
355}
356
357Connection* TurnPort::CreateConnection(const Candidate& address,
358 CandidateOrigin origin) {
359 // TURN-UDP can only connect to UDP candidates.
360 if (address.protocol() != UDP_PROTOCOL_NAME) {
361 return NULL;
362 }
363
364 if (!IsCompatibleAddress(address.address())) {
365 return NULL;
366 }
367
368 // Create an entry, if needed, so we can get our permissions set up correctly.
369 CreateEntry(address.address());
370
371 // A TURN port will have two candiates, STUN and TURN. STUN may not
372 // present in all cases. If present stun candidate will be added first
373 // and TURN candidate later.
374 for (size_t index = 0; index < Candidates().size(); ++index) {
375 if (Candidates()[index].type() == RELAY_PORT_TYPE) {
376 ProxyConnection* conn = new ProxyConnection(this, index, address);
377 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
378 AddConnection(conn);
379 return conn;
380 }
381 }
382 return NULL;
383}
384
385int TurnPort::SetOption(rtc::Socket::Option opt, int value) {
386 if (!socket_) {
387 // If socket is not created yet, these options will be applied during socket
388 // creation.
389 socket_options_[opt] = value;
390 return 0;
391 }
392 return socket_->SetOption(opt, value);
393}
394
395int TurnPort::GetOption(rtc::Socket::Option opt, int* value) {
396 if (!socket_) {
397 SocketOptionsMap::const_iterator it = socket_options_.find(opt);
398 if (it == socket_options_.end()) {
399 return -1;
400 }
401 *value = it->second;
402 return 0;
403 }
404
405 return socket_->GetOption(opt, value);
406}
407
408int TurnPort::GetError() {
409 return error_;
410}
411
412int TurnPort::SendTo(const void* data, size_t size,
413 const rtc::SocketAddress& addr,
414 const rtc::PacketOptions& options,
415 bool payload) {
416 // Try to find an entry for this specific address; we should have one.
417 TurnEntry* entry = FindEntry(addr);
418 ASSERT(entry != NULL);
419 if (!entry) {
420 return 0;
421 }
422
423 if (!connected()) {
424 error_ = EWOULDBLOCK;
425 return SOCKET_ERROR;
426 }
427
428 // Send the actual contents to the server using the usual mechanism.
429 int sent = entry->Send(data, size, payload, options);
430 if (sent <= 0) {
431 return SOCKET_ERROR;
432 }
433
434 // The caller of the function is expecting the number of user data bytes,
435 // rather than the size of the packet.
436 return static_cast<int>(size);
437}
438
439void TurnPort::OnReadPacket(
440 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
441 const rtc::SocketAddress& remote_addr,
442 const rtc::PacketTime& packet_time) {
443 ASSERT(socket == socket_);
444 ASSERT(remote_addr == server_address_.address);
445
446 // The message must be at least the size of a channel header.
447 if (size < TURN_CHANNEL_HEADER_SIZE) {
448 LOG_J(LS_WARNING, this) << "Received TURN message that was too short";
449 return;
450 }
451
452 // Check the message type, to see if is a Channel Data message.
453 // The message will either be channel data, a TURN data indication, or
454 // a response to a previous request.
455 uint16 msg_type = rtc::GetBE16(data);
456 if (IsTurnChannelData(msg_type)) {
457 HandleChannelData(msg_type, data, size, packet_time);
458 } else if (msg_type == TURN_DATA_INDICATION) {
459 HandleDataIndication(data, size, packet_time);
460 } else {
461 // This must be a response for one of our requests.
462 // Check success responses, but not errors, for MESSAGE-INTEGRITY.
463 if (IsStunSuccessResponseType(msg_type) &&
464 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
465 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
466 << "message integrity, msg_type=" << msg_type;
467 return;
468 }
469 request_manager_.CheckResponse(data, size);
470 }
471}
472
473void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
474 if (connected_) {
475 Port::OnReadyToSend();
476 }
477}
478
479
480// Update current server address port with the alternate server address port.
481bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
482 // Check if we have seen this address before and reject if we did.
483 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
484 if (iter != attempted_server_addresses_.end()) {
485 LOG_J(LS_WARNING, this) << "Redirection to ["
486 << address.ToSensitiveString()
487 << "] ignored, allocation failed.";
488 return false;
489 }
490
491 // If protocol family of server address doesn't match with local, return.
492 if (!IsCompatibleAddress(address)) {
493 LOG(LS_WARNING) << "Server IP address family does not match with "
494 << "local host address family type";
495 return false;
496 }
497
498 LOG_J(LS_INFO, this) << "Redirecting from TURN server ["
499 << server_address_.address.ToSensitiveString()
500 << "] to TURN server ["
501 << address.ToSensitiveString()
502 << "]";
503 server_address_ = ProtocolAddress(address, server_address_.proto,
504 server_address_.secure);
505
506 // Insert the current address to prevent redirection pingpong.
507 attempted_server_addresses_.insert(server_address_.address);
508 return true;
509}
510
511void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) {
512 if (resolver_)
513 return;
514
515 resolver_ = socket_factory()->CreateAsyncResolver();
516 resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
517 resolver_->Start(address);
518}
519
520void TurnPort::OnResolveResult(rtc::AsyncResolverInterface* resolver) {
521 ASSERT(resolver == resolver_);
522 // If DNS resolve is failed when trying to connect to the server using TCP,
523 // one of the reason could be due to DNS queries blocked by firewall.
524 // In such cases we will try to connect to the server with hostname, assuming
525 // socket layer will resolve the hostname through a HTTP proxy (if any).
526 if (resolver_->GetError() != 0 && server_address_.proto == PROTO_TCP) {
527 if (!CreateTurnClientSocket()) {
528 OnAllocateError();
529 }
530 return;
531 }
532
533 // Copy the original server address in |resolved_address|. For TLS based
534 // sockets we need hostname along with resolved address.
535 rtc::SocketAddress resolved_address = server_address_.address;
536 if (resolver_->GetError() != 0 ||
537 !resolver_->GetResolvedAddress(ip().family(), &resolved_address)) {
538 LOG_J(LS_WARNING, this) << "TURN host lookup received error "
539 << resolver_->GetError();
540 error_ = resolver_->GetError();
541 OnAllocateError();
542 return;
543 }
544 // Signal needs both resolved and unresolved address. After signal is sent
545 // we can copy resolved address back into |server_address_|.
546 SignalResolvedServerAddress(this, server_address_.address,
547 resolved_address);
548 server_address_.address = resolved_address;
549 PrepareAddress();
550}
551
552void TurnPort::OnSendStunPacket(const void* data, size_t size,
553 StunRequest* request) {
554 rtc::PacketOptions options(DefaultDscpValue());
555 if (Send(data, size, options) < 0) {
556 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
557 << socket_->GetError();
558 }
559}
560
561void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
562 // STUN Port will discover STUN candidate, as it's supplied with first TURN
563 // server address.
564 // Why not using this address? - P2PTransportChannel will start creating
565 // connections after first candidate, which means it could start creating the
566 // connections before TURN candidate added. For that to handle, we need to
567 // supply STUN candidate from this port to UDPPort, and TurnPort should have
568 // handle to UDPPort to pass back the address.
569}
570
571void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
572 const rtc::SocketAddress& stun_address) {
573 connected_ = true;
574
575 rtc::SocketAddress related_address = stun_address;
576 if (!(candidate_filter() & CF_REFLEXIVE)) {
577 // If candidate filter only allows relay type of address, empty raddr to
578 // avoid local address leakage.
579 related_address = rtc::EmptySocketAddressWithFamily(stun_address.family());
580 }
581
582 // For relayed candidate, Base is the candidate itself.
583 AddAddress(address, // Candidate address.
584 address, // Base address.
585 related_address, // Related address.
586 UDP_PROTOCOL_NAME,
587 "", // TCP canddiate type, empty for turn candidates.
588 RELAY_PORT_TYPE,
589 GetRelayPreference(server_address_.proto, server_address_.secure),
590 server_priority_,
591 true);
592}
593
594void TurnPort::OnAllocateError() {
595 // We will send SignalPortError asynchronously as this can be sent during
596 // port initialization. This way it will not be blocking other port
597 // creation.
598 thread()->Post(this, MSG_ERROR);
599}
600
601void TurnPort::OnMessage(rtc::Message* message) {
602 if (message->message_id == MSG_ERROR) {
603 SignalPortError(this);
604 return;
605 } else if (message->message_id == MSG_ALLOCATE_MISMATCH) {
606 OnAllocateMismatch();
607 return;
608 }
609
610 Port::OnMessage(message);
611}
612
613void TurnPort::OnAllocateRequestTimeout() {
614 OnAllocateError();
615}
616
617void TurnPort::HandleDataIndication(const char* data, size_t size,
618 const rtc::PacketTime& packet_time) {
619 // Read in the message, and process according to RFC5766, Section 10.4.
620 rtc::ByteBuffer buf(data, size);
621 TurnMessage msg;
622 if (!msg.Read(&buf)) {
623 LOG_J(LS_WARNING, this) << "Received invalid TURN data indication";
624 return;
625 }
626
627 // Check mandatory attributes.
628 const StunAddressAttribute* addr_attr =
629 msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
630 if (!addr_attr) {
631 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
632 << "in data indication.";
633 return;
634 }
635
636 const StunByteStringAttribute* data_attr =
637 msg.GetByteString(STUN_ATTR_DATA);
638 if (!data_attr) {
639 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_DATA attribute in "
640 << "data indication.";
641 return;
642 }
643
644 // Verify that the data came from somewhere we think we have a permission for.
645 rtc::SocketAddress ext_addr(addr_attr->GetAddress());
646 if (!HasPermission(ext_addr.ipaddr())) {
647 LOG_J(LS_WARNING, this) << "Received TURN data indication with invalid "
648 << "peer address, addr="
649 << ext_addr.ToSensitiveString();
650 return;
651 }
652
653 DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr,
654 PROTO_UDP, packet_time);
655}
656
657void TurnPort::HandleChannelData(int channel_id, const char* data,
658 size_t size,
659 const rtc::PacketTime& packet_time) {
660 // Read the message, and process according to RFC5766, Section 11.6.
661 // 0 1 2 3
662 // 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
663 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
664 // | Channel Number | Length |
665 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
666 // | |
667 // / Application Data /
668 // / /
669 // | |
670 // | +-------------------------------+
671 // | |
672 // +-------------------------------+
673
674 // Extract header fields from the message.
675 uint16 len = rtc::GetBE16(data + 2);
676 if (len > size - TURN_CHANNEL_HEADER_SIZE) {
677 LOG_J(LS_WARNING, this) << "Received TURN channel data message with "
678 << "incorrect length, len=" << len;
679 return;
680 }
681 // Allowing messages larger than |len|, as ChannelData can be padded.
682
683 TurnEntry* entry = FindEntry(channel_id);
684 if (!entry) {
685 LOG_J(LS_WARNING, this) << "Received TURN channel data message for invalid "
686 << "channel, channel_id=" << channel_id;
687 return;
688 }
689
690 DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
691 PROTO_UDP, packet_time);
692}
693
694void TurnPort::DispatchPacket(const char* data, size_t size,
695 const rtc::SocketAddress& remote_addr,
696 ProtocolType proto, const rtc::PacketTime& packet_time) {
697 if (Connection* conn = GetConnection(remote_addr)) {
698 conn->OnReadPacket(data, size, packet_time);
699 } else {
700 Port::OnReadPacket(data, size, remote_addr, proto);
701 }
702}
703
704bool TurnPort::ScheduleRefresh(int lifetime) {
705 // Lifetime is in seconds; we schedule a refresh for one minute less.
706 if (lifetime < 2 * 60) {
707 LOG_J(LS_WARNING, this) << "Received response with lifetime that was "
708 << "too short, lifetime=" << lifetime;
709 return false;
710 }
711
712 SendRequest(new TurnRefreshRequest(this), (lifetime - 60) * 1000);
713 return true;
714}
715
716void TurnPort::SendRequest(StunRequest* req, int delay) {
717 request_manager_.SendDelayed(req, delay);
718}
719
720void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
721 // If we've gotten the necessary data from the server, add it to our request.
722 VERIFY(!hash_.empty());
723 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
724 STUN_ATTR_USERNAME, credentials_.username)));
725 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
726 STUN_ATTR_REALM, realm_)));
727 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
728 STUN_ATTR_NONCE, nonce_)));
729 VERIFY(msg->AddMessageIntegrity(hash()));
730}
731
732int TurnPort::Send(const void* data, size_t len,
733 const rtc::PacketOptions& options) {
734 return socket_->SendTo(data, len, server_address_.address, options);
735}
736
737void TurnPort::UpdateHash() {
738 VERIFY(ComputeStunCredentialHash(credentials_.username, realm_,
739 credentials_.password, &hash_));
740}
741
742bool TurnPort::UpdateNonce(StunMessage* response) {
743 // When stale nonce error received, we should update
744 // hash and store realm and nonce.
745 // Check the mandatory attributes.
746 const StunByteStringAttribute* realm_attr =
747 response->GetByteString(STUN_ATTR_REALM);
748 if (!realm_attr) {
749 LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
750 << "stale nonce error response.";
751 return false;
752 }
753 set_realm(realm_attr->GetString());
754
755 const StunByteStringAttribute* nonce_attr =
756 response->GetByteString(STUN_ATTR_NONCE);
757 if (!nonce_attr) {
758 LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
759 << "stale nonce error response.";
760 return false;
761 }
762 set_nonce(nonce_attr->GetString());
763 return true;
764}
765
766static bool MatchesIP(TurnEntry* e, rtc::IPAddress ipaddr) {
767 return e->address().ipaddr() == ipaddr;
768}
769bool TurnPort::HasPermission(const rtc::IPAddress& ipaddr) const {
770 return (std::find_if(entries_.begin(), entries_.end(),
771 std::bind2nd(std::ptr_fun(MatchesIP), ipaddr)) != entries_.end());
772}
773
774static bool MatchesAddress(TurnEntry* e, rtc::SocketAddress addr) {
775 return e->address() == addr;
776}
777TurnEntry* TurnPort::FindEntry(const rtc::SocketAddress& addr) const {
778 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
779 std::bind2nd(std::ptr_fun(MatchesAddress), addr));
780 return (it != entries_.end()) ? *it : NULL;
781}
782
783static bool MatchesChannelId(TurnEntry* e, int id) {
784 return e->channel_id() == id;
785}
786TurnEntry* TurnPort::FindEntry(int channel_id) const {
787 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
788 std::bind2nd(std::ptr_fun(MatchesChannelId), channel_id));
789 return (it != entries_.end()) ? *it : NULL;
790}
791
792TurnEntry* TurnPort::CreateEntry(const rtc::SocketAddress& addr) {
793 ASSERT(FindEntry(addr) == NULL);
794 TurnEntry* entry = new TurnEntry(this, next_channel_number_++, addr);
795 entries_.push_back(entry);
796 return entry;
797}
798
799void TurnPort::DestroyEntry(const rtc::SocketAddress& addr) {
800 TurnEntry* entry = FindEntry(addr);
801 ASSERT(entry != NULL);
802 entry->SignalDestroyed(entry);
803 entries_.remove(entry);
804 delete entry;
805}
806
807void TurnPort::OnConnectionDestroyed(Connection* conn) {
808 // Destroying TurnEntry for the connection, which is already destroyed.
809 DestroyEntry(conn->remote_candidate().address());
810}
811
812TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
813 : StunRequest(new TurnMessage()),
814 port_(port) {
815}
816
817void TurnAllocateRequest::Prepare(StunMessage* request) {
818 // Create the request as indicated in RFC 5766, Section 6.1.
819 request->SetType(TURN_ALLOCATE_REQUEST);
820 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
821 STUN_ATTR_REQUESTED_TRANSPORT);
822 transport_attr->SetValue(IPPROTO_UDP << 24);
823 VERIFY(request->AddAttribute(transport_attr));
824 if (!port_->hash().empty()) {
825 port_->AddRequestAuthInfo(request);
826 }
827}
828
829void TurnAllocateRequest::OnResponse(StunMessage* response) {
830 // Check mandatory attributes as indicated in RFC5766, Section 6.3.
831 const StunAddressAttribute* mapped_attr =
832 response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
833 if (!mapped_attr) {
834 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
835 << "attribute in allocate success response";
836 return;
837 }
838 // Using XOR-Mapped-Address for stun.
839 port_->OnStunAddress(mapped_attr->GetAddress());
840
841 const StunAddressAttribute* relayed_attr =
842 response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
843 if (!relayed_attr) {
844 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
845 << "attribute in allocate success response";
846 return;
847 }
848
849 const StunUInt32Attribute* lifetime_attr =
850 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
851 if (!lifetime_attr) {
852 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
853 << "allocate success response";
854 return;
855 }
856 // Notify the port the allocate succeeded, and schedule a refresh request.
857 port_->OnAllocateSuccess(relayed_attr->GetAddress(),
858 mapped_attr->GetAddress());
859 port_->ScheduleRefresh(lifetime_attr->value());
860}
861
862void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
863 // Process error response according to RFC5766, Section 6.4.
864 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
865 switch (error_code->code()) {
866 case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
867 OnAuthChallenge(response, error_code->code());
868 break;
869 case STUN_ERROR_TRY_ALTERNATE:
870 OnTryAlternate(response, error_code->code());
871 break;
872 case STUN_ERROR_ALLOCATION_MISMATCH:
873 // We must handle this error async because trying to delete the socket in
874 // OnErrorResponse will cause a deadlock on the socket.
875 port_->thread()->Post(port_, TurnPort::MSG_ALLOCATE_MISMATCH);
876 break;
877 default:
878 LOG_J(LS_WARNING, port_) << "Allocate response error, code="
879 << error_code->code();
880 port_->OnAllocateError();
881 }
882}
883
884void TurnAllocateRequest::OnTimeout() {
885 LOG_J(LS_WARNING, port_) << "Allocate request timeout";
886 port_->OnAllocateRequestTimeout();
887}
888
889void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
890 // If we failed to authenticate even after we sent our credentials, fail hard.
891 if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
892 LOG_J(LS_WARNING, port_) << "Failed to authenticate with the server "
893 << "after challenge.";
894 port_->OnAllocateError();
895 return;
896 }
897
898 // Check the mandatory attributes.
899 const StunByteStringAttribute* realm_attr =
900 response->GetByteString(STUN_ATTR_REALM);
901 if (!realm_attr) {
902 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_REALM attribute in "
903 << "allocate unauthorized response.";
904 return;
905 }
906 port_->set_realm(realm_attr->GetString());
907
908 const StunByteStringAttribute* nonce_attr =
909 response->GetByteString(STUN_ATTR_NONCE);
910 if (!nonce_attr) {
911 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_NONCE attribute in "
912 << "allocate unauthorized response.";
913 return;
914 }
915 port_->set_nonce(nonce_attr->GetString());
916
917 // Send another allocate request, with the received realm and nonce values.
918 port_->SendRequest(new TurnAllocateRequest(port_), 0);
919}
920
921void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
922 // TODO(guoweis): Currently, we only support UDP redirect
923 if (port_->server_address().proto != PROTO_UDP) {
924 LOG_J(LS_WARNING, port_) << "Receiving 300 Alternate Server on non-UDP "
925 << "allocating request from ["
926 << port_->server_address().address.ToSensitiveString()
927 << "], failed as currently not supported";
928 port_->OnAllocateError();
929 return;
930 }
931
932 // According to RFC 5389 section 11, there are use cases where
933 // authentication of response is not possible, we're not validating
934 // message integrity.
935
936 // Get the alternate server address attribute value.
937 const StunAddressAttribute* alternate_server_attr =
938 response->GetAddress(STUN_ATTR_ALTERNATE_SERVER);
939 if (!alternate_server_attr) {
940 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_ALTERNATE_SERVER "
941 << "attribute in try alternate error response";
942 port_->OnAllocateError();
943 return;
944 }
945 if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) {
946 port_->OnAllocateError();
947 return;
948 }
949
950 // Check the attributes.
951 const StunByteStringAttribute* realm_attr =
952 response->GetByteString(STUN_ATTR_REALM);
953 if (realm_attr) {
954 LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_REALM attribute in "
955 << "try alternate error response.";
956 port_->set_realm(realm_attr->GetString());
957 }
958
959 const StunByteStringAttribute* nonce_attr =
960 response->GetByteString(STUN_ATTR_NONCE);
961 if (nonce_attr) {
962 LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_NONCE attribute in "
963 << "try alternate error response.";
964 port_->set_nonce(nonce_attr->GetString());
965 }
966
967 // Send another allocate request to alternate server,
968 // with the received realm and nonce values.
969 port_->SendRequest(new TurnAllocateRequest(port_), 0);
970}
971
972TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
973 : StunRequest(new TurnMessage()),
974 port_(port) {
975}
976
977void TurnRefreshRequest::Prepare(StunMessage* request) {
978 // Create the request as indicated in RFC 5766, Section 7.1.
979 // No attributes need to be included.
980 request->SetType(TURN_REFRESH_REQUEST);
981 port_->AddRequestAuthInfo(request);
982}
983
984void TurnRefreshRequest::OnResponse(StunMessage* response) {
985 // Check mandatory attributes as indicated in RFC5766, Section 7.3.
986 const StunUInt32Attribute* lifetime_attr =
987 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
988 if (!lifetime_attr) {
989 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
990 << "refresh success response.";
991 return;
992 }
993
994 // Schedule a refresh based on the returned lifetime value.
995 port_->ScheduleRefresh(lifetime_attr->value());
996}
997
998void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
999 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1000 LOG_J(LS_WARNING, port_) << "Refresh response error, code="
1001 << error_code->code();
1002
1003 if (error_code->code() == STUN_ERROR_STALE_NONCE) {
1004 if (port_->UpdateNonce(response)) {
1005 // Send RefreshRequest immediately.
1006 port_->SendRequest(new TurnRefreshRequest(port_), 0);
1007 }
1008 }
1009}
1010
1011void TurnRefreshRequest::OnTimeout() {
1012}
1013
1014TurnCreatePermissionRequest::TurnCreatePermissionRequest(
1015 TurnPort* port, TurnEntry* entry,
1016 const rtc::SocketAddress& ext_addr)
1017 : StunRequest(new TurnMessage()),
1018 port_(port),
1019 entry_(entry),
1020 ext_addr_(ext_addr) {
1021 entry_->SignalDestroyed.connect(
1022 this, &TurnCreatePermissionRequest::OnEntryDestroyed);
1023}
1024
1025void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
1026 // Create the request as indicated in RFC5766, Section 9.1.
1027 request->SetType(TURN_CREATE_PERMISSION_REQUEST);
1028 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
1029 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1030 port_->AddRequestAuthInfo(request);
1031}
1032
1033void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
1034 if (entry_) {
1035 entry_->OnCreatePermissionSuccess();
1036 }
1037}
1038
1039void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
1040 if (entry_) {
1041 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1042 entry_->OnCreatePermissionError(response, error_code->code());
1043 }
1044}
1045
1046void TurnCreatePermissionRequest::OnTimeout() {
1047 LOG_J(LS_WARNING, port_) << "Create permission timeout";
1048}
1049
1050void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
1051 ASSERT(entry_ == entry);
1052 entry_ = NULL;
1053}
1054
1055TurnChannelBindRequest::TurnChannelBindRequest(
1056 TurnPort* port, TurnEntry* entry,
1057 int channel_id, const rtc::SocketAddress& ext_addr)
1058 : StunRequest(new TurnMessage()),
1059 port_(port),
1060 entry_(entry),
1061 channel_id_(channel_id),
1062 ext_addr_(ext_addr) {
1063 entry_->SignalDestroyed.connect(
1064 this, &TurnChannelBindRequest::OnEntryDestroyed);
1065}
1066
1067void TurnChannelBindRequest::Prepare(StunMessage* request) {
1068 // Create the request as indicated in RFC5766, Section 11.1.
1069 request->SetType(TURN_CHANNEL_BIND_REQUEST);
1070 VERIFY(request->AddAttribute(new StunUInt32Attribute(
1071 STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16)));
1072 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
1073 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1074 port_->AddRequestAuthInfo(request);
1075}
1076
1077void TurnChannelBindRequest::OnResponse(StunMessage* response) {
1078 if (entry_) {
1079 entry_->OnChannelBindSuccess();
1080 // Refresh the channel binding just under the permission timeout
1081 // threshold. The channel binding has a longer lifetime, but
1082 // this is the easiest way to keep both the channel and the
1083 // permission from expiring.
1084 entry_->SendChannelBindRequest(TURN_PERMISSION_TIMEOUT - 60 * 1000);
1085 }
1086}
1087
1088void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
1089 if (entry_) {
1090 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1091 entry_->OnChannelBindError(response, error_code->code());
1092 }
1093}
1094
1095void TurnChannelBindRequest::OnTimeout() {
1096 LOG_J(LS_WARNING, port_) << "Channel bind timeout";
1097}
1098
1099void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
1100 ASSERT(entry_ == entry);
1101 entry_ = NULL;
1102}
1103
1104TurnEntry::TurnEntry(TurnPort* port, int channel_id,
1105 const rtc::SocketAddress& ext_addr)
1106 : port_(port),
1107 channel_id_(channel_id),
1108 ext_addr_(ext_addr),
1109 state_(STATE_UNBOUND) {
1110 // Creating permission for |ext_addr_|.
1111 SendCreatePermissionRequest();
1112}
1113
1114void TurnEntry::SendCreatePermissionRequest() {
1115 port_->SendRequest(new TurnCreatePermissionRequest(
1116 port_, this, ext_addr_), 0);
1117}
1118
1119void TurnEntry::SendChannelBindRequest(int delay) {
1120 port_->SendRequest(new TurnChannelBindRequest(
1121 port_, this, channel_id_, ext_addr_), delay);
1122}
1123
1124int TurnEntry::Send(const void* data, size_t size, bool payload,
1125 const rtc::PacketOptions& options) {
1126 rtc::ByteBuffer buf;
1127 if (state_ != STATE_BOUND) {
1128 // If we haven't bound the channel yet, we have to use a Send Indication.
1129 TurnMessage msg;
1130 msg.SetType(TURN_SEND_INDICATION);
1131 msg.SetTransactionID(
1132 rtc::CreateRandomString(kStunTransactionIdLength));
1133 VERIFY(msg.AddAttribute(new StunXorAddressAttribute(
1134 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1135 VERIFY(msg.AddAttribute(new StunByteStringAttribute(
1136 STUN_ATTR_DATA, data, size)));
1137 VERIFY(msg.Write(&buf));
1138
1139 // If we're sending real data, request a channel bind that we can use later.
1140 if (state_ == STATE_UNBOUND && payload) {
1141 SendChannelBindRequest(0);
1142 state_ = STATE_BINDING;
1143 }
1144 } else {
1145 // If the channel is bound, we can send the data as a Channel Message.
1146 buf.WriteUInt16(channel_id_);
1147 buf.WriteUInt16(static_cast<uint16>(size));
1148 buf.WriteBytes(reinterpret_cast<const char*>(data), size);
1149 }
1150 return port_->Send(buf.Data(), buf.Length(), options);
1151}
1152
1153void TurnEntry::OnCreatePermissionSuccess() {
1154 LOG_J(LS_INFO, port_) << "Create permission for "
1155 << ext_addr_.ToSensitiveString()
1156 << " succeeded";
1157 // For success result code will be 0.
1158 port_->SignalCreatePermissionResult(port_, ext_addr_, 0);
1159}
1160
1161void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
1162 LOG_J(LS_WARNING, port_) << "Create permission for "
1163 << ext_addr_.ToSensitiveString()
1164 << " failed, code=" << code;
1165 if (code == STUN_ERROR_STALE_NONCE) {
1166 if (port_->UpdateNonce(response)) {
1167 SendCreatePermissionRequest();
1168 }
1169 } else {
1170 // Send signal with error code.
1171 port_->SignalCreatePermissionResult(port_, ext_addr_, code);
1172 }
1173}
1174
1175void TurnEntry::OnChannelBindSuccess() {
1176 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString()
1177 << " succeeded";
1178 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND);
1179 state_ = STATE_BOUND;
1180}
1181
1182void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1183 // TODO(mallinath) - Implement handling of error response for channel
1184 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
1185 LOG_J(LS_WARNING, port_) << "Channel bind for "
1186 << ext_addr_.ToSensitiveString()
1187 << " failed, code=" << code;
1188 if (code == STUN_ERROR_STALE_NONCE) {
1189 if (port_->UpdateNonce(response)) {
1190 // Send channel bind request with fresh nonce.
1191 SendChannelBindRequest(0);
1192 }
1193 }
1194}
1195
1196} // namespace cricket