3 * Copyright 2012, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "talk/p2p/base/turnport.h"
32 #include "talk/p2p/base/common.h"
33 #include "talk/p2p/base/stun.h"
34 #include "webrtc/base/asyncpacketsocket.h"
35 #include "webrtc/base/byteorder.h"
36 #include "webrtc/base/common.h"
37 #include "webrtc/base/logging.h"
38 #include "webrtc/base/nethelpers.h"
39 #include "webrtc/base/socketaddress.h"
40 #include "webrtc/base/stringencode.h"
44 // TODO(juberti): Move to stun.h when relay messages have been renamed.
45 static const int TURN_ALLOCATE_REQUEST = STUN_ALLOCATE_REQUEST;
47 // TODO(juberti): Extract to turnmessage.h
48 static const int TURN_DEFAULT_PORT = 3478;
49 static const int TURN_CHANNEL_NUMBER_START = 0x4000;
50 static const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
52 static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
54 // Retry at most twice (i.e. three different ALLOCATE requests) on
55 // STUN_ERROR_ALLOCATION_MISMATCH error per rfc5766.
56 static const size_t MAX_ALLOCATE_MISMATCH_RETRIES = 2;
58 inline bool IsTurnChannelData(uint16 msg_type) {
59 return ((msg_type & 0xC000) == 0x4000); // MSB are 0b01
62 static int GetRelayPreference(cricket::ProtocolType proto, bool secure) {
63 int relay_preference = ICE_TYPE_PREFERENCE_RELAY;
64 if (proto == cricket::PROTO_TCP) {
65 relay_preference -= 1;
67 relay_preference -= 1;
70 ASSERT(relay_preference >= 0);
71 return relay_preference;
74 class TurnAllocateRequest : public StunRequest {
76 explicit TurnAllocateRequest(TurnPort* port);
77 virtual void Prepare(StunMessage* request);
78 virtual void OnResponse(StunMessage* response);
79 virtual void OnErrorResponse(StunMessage* response);
80 virtual void OnTimeout();
83 // Handles authentication challenge from the server.
84 void OnAuthChallenge(StunMessage* response, int code);
85 void OnTryAlternate(StunMessage* response, int code);
86 void OnUnknownAttribute(StunMessage* response);
91 class TurnRefreshRequest : public StunRequest {
93 explicit TurnRefreshRequest(TurnPort* port);
94 virtual void Prepare(StunMessage* request);
95 virtual void OnResponse(StunMessage* response);
96 virtual void OnErrorResponse(StunMessage* response);
97 virtual void OnTimeout();
103 class TurnCreatePermissionRequest : public StunRequest,
104 public sigslot::has_slots<> {
106 TurnCreatePermissionRequest(TurnPort* port, TurnEntry* entry,
107 const rtc::SocketAddress& ext_addr);
108 virtual void Prepare(StunMessage* request);
109 virtual void OnResponse(StunMessage* response);
110 virtual void OnErrorResponse(StunMessage* response);
111 virtual void OnTimeout();
114 void OnEntryDestroyed(TurnEntry* entry);
118 rtc::SocketAddress ext_addr_;
121 class TurnChannelBindRequest : public StunRequest,
122 public sigslot::has_slots<> {
124 TurnChannelBindRequest(TurnPort* port, TurnEntry* entry, int channel_id,
125 const rtc::SocketAddress& ext_addr);
126 virtual void Prepare(StunMessage* request);
127 virtual void OnResponse(StunMessage* response);
128 virtual void OnErrorResponse(StunMessage* response);
129 virtual void OnTimeout();
132 void OnEntryDestroyed(TurnEntry* entry);
137 rtc::SocketAddress ext_addr_;
140 // Manages a "connection" to a remote destination. We will attempt to bring up
141 // a channel for this remote destination to reduce the overhead of sending data.
142 class TurnEntry : public sigslot::has_slots<> {
144 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
145 TurnEntry(TurnPort* port, int channel_id,
146 const rtc::SocketAddress& ext_addr);
148 TurnPort* port() { return port_; }
150 int channel_id() const { return channel_id_; }
151 const rtc::SocketAddress& address() const { return ext_addr_; }
152 BindState state() const { return state_; }
154 // Helper methods to send permission and channel bind requests.
155 void SendCreatePermissionRequest();
156 void SendChannelBindRequest(int delay);
157 // Sends a packet to the given destination address.
158 // This will wrap the packet in STUN if necessary.
159 int Send(const void* data, size_t size, bool payload,
160 const rtc::PacketOptions& options);
162 void OnCreatePermissionSuccess();
163 void OnCreatePermissionError(StunMessage* response, int code);
164 void OnChannelBindSuccess();
165 void OnChannelBindError(StunMessage* response, int code);
166 // Signal sent when TurnEntry is destroyed.
167 sigslot::signal1<TurnEntry*> SignalDestroyed;
172 rtc::SocketAddress ext_addr_;
176 TurnPort::TurnPort(rtc::Thread* thread,
177 rtc::PacketSocketFactory* factory,
178 rtc::Network* network,
179 rtc::AsyncPacketSocket* socket,
180 const std::string& username,
181 const std::string& password,
182 const ProtocolAddress& server_address,
183 const RelayCredentials& credentials,
185 : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
187 server_address_(server_address),
188 credentials_(credentials),
192 request_manager_(thread),
193 next_channel_number_(TURN_CHANNEL_NUMBER_START),
195 server_priority_(server_priority),
196 allocate_mismatch_retries_(0) {
197 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
200 TurnPort::TurnPort(rtc::Thread* thread,
201 rtc::PacketSocketFactory* factory,
202 rtc::Network* network,
203 const rtc::IPAddress& ip,
204 int min_port, int max_port,
205 const std::string& username,
206 const std::string& password,
207 const ProtocolAddress& server_address,
208 const RelayCredentials& credentials,
210 : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port,
212 server_address_(server_address),
213 credentials_(credentials),
217 request_manager_(thread),
218 next_channel_number_(TURN_CHANNEL_NUMBER_START),
220 server_priority_(server_priority),
221 allocate_mismatch_retries_(0) {
222 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
225 TurnPort::~TurnPort() {
226 // TODO(juberti): Should this even be necessary?
227 while (!entries_.empty()) {
228 DestroyEntry(entries_.front()->address());
231 resolver_->Destroy(false);
233 if (!SharedSocket()) {
238 void TurnPort::PrepareAddress() {
239 if (credentials_.username.empty() ||
240 credentials_.password.empty()) {
241 LOG(LS_ERROR) << "Allocation can't be started without setting the"
242 << " TURN server credentials for the user.";
247 if (!server_address_.address.port()) {
248 // We will set default TURN port, if no port is set in the address.
249 server_address_.address.SetPort(TURN_DEFAULT_PORT);
252 if (server_address_.address.IsUnresolved()) {
253 ResolveTurnAddress(server_address_.address);
255 // If protocol family of server address doesn't match with local, return.
256 if (!IsCompatibleAddress(server_address_.address)) {
257 LOG(LS_ERROR) << "Server IP address family does not match with "
258 << "local host address family type";
263 // Insert the current address to prevent redirection pingpong.
264 attempted_server_addresses_.insert(server_address_.address);
266 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
267 << ProtoToString(server_address_.proto) << " @ "
268 << server_address_.address.ToSensitiveString();
269 if (!CreateTurnClientSocket()) {
271 } else if (server_address_.proto == PROTO_UDP) {
272 // If its UDP, send AllocateRequest now.
273 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
274 SendRequest(new TurnAllocateRequest(this), 0);
279 bool TurnPort::CreateTurnClientSocket() {
280 ASSERT(!socket_ || SharedSocket());
282 if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
283 socket_ = socket_factory()->CreateUdpSocket(
284 rtc::SocketAddress(ip(), 0), min_port(), max_port());
285 } else if (server_address_.proto == PROTO_TCP) {
286 ASSERT(!SharedSocket());
287 int opts = rtc::PacketSocketFactory::OPT_STUN;
288 // If secure bit is enabled in server address, use TLS over TCP.
289 if (server_address_.secure) {
290 opts |= rtc::PacketSocketFactory::OPT_TLS;
292 socket_ = socket_factory()->CreateClientTcpSocket(
293 rtc::SocketAddress(ip(), 0), server_address_.address,
294 proxy(), user_agent(), opts);
298 error_ = SOCKET_ERROR;
302 // Apply options if any.
303 for (SocketOptionsMap::iterator iter = socket_options_.begin();
304 iter != socket_options_.end(); ++iter) {
305 socket_->SetOption(iter->first, iter->second);
308 if (!SharedSocket()) {
309 // If socket is shared, AllocationSequence will receive the packet.
310 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
313 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
315 if (server_address_.proto == PROTO_TCP) {
316 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
317 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
322 void TurnPort::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
323 ASSERT(server_address_.proto == PROTO_TCP);
324 // Do not use this port if the socket bound to a different address than
325 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be
326 // given a binding address, and the platform is expected to pick the
327 // correct local address.
328 if (socket->GetLocalAddress().ipaddr() != ip()) {
329 LOG(LS_WARNING) << "Socket is bound to a different address then the "
330 << "local port. Discarding TURN port.";
335 if (server_address_.address.IsUnresolved()) {
336 server_address_.address = socket_->GetRemoteAddress();
339 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
341 SendRequest(new TurnAllocateRequest(this), 0);
344 void TurnPort::OnSocketClose(rtc::AsyncPacketSocket* socket, int error) {
345 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
351 void TurnPort::OnAllocateMismatch() {
352 if (allocate_mismatch_retries_ >= MAX_ALLOCATE_MISMATCH_RETRIES) {
353 LOG_J(LS_WARNING, this) << "Giving up on the port after "
354 << allocate_mismatch_retries_
355 << " retries for STUN_ERROR_ALLOCATION_MISMATCH";
360 LOG_J(LS_INFO, this) << "Allocating a new socket after "
361 << "STUN_ERROR_ALLOCATION_MISMATCH, retry = "
362 << allocate_mismatch_retries_ + 1;
363 if (SharedSocket()) {
371 ++allocate_mismatch_retries_;
374 Connection* TurnPort::CreateConnection(const Candidate& address,
375 CandidateOrigin origin) {
376 // TURN-UDP can only connect to UDP candidates.
377 if (address.protocol() != UDP_PROTOCOL_NAME) {
381 if (!IsCompatibleAddress(address.address())) {
385 // Create an entry, if needed, so we can get our permissions set up correctly.
386 CreateEntry(address.address());
388 // A TURN port will have two candiates, STUN and TURN. STUN may not
389 // present in all cases. If present stun candidate will be added first
390 // and TURN candidate later.
391 for (size_t index = 0; index < Candidates().size(); ++index) {
392 if (Candidates()[index].type() == RELAY_PORT_TYPE) {
393 ProxyConnection* conn = new ProxyConnection(this, index, address);
394 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
402 int TurnPort::SetOption(rtc::Socket::Option opt, int value) {
404 // If socket is not created yet, these options will be applied during socket
406 socket_options_[opt] = value;
409 return socket_->SetOption(opt, value);
412 int TurnPort::GetOption(rtc::Socket::Option opt, int* value) {
414 SocketOptionsMap::const_iterator it = socket_options_.find(opt);
415 if (it == socket_options_.end()) {
422 return socket_->GetOption(opt, value);
425 int TurnPort::GetError() {
429 int TurnPort::SendTo(const void* data, size_t size,
430 const rtc::SocketAddress& addr,
431 const rtc::PacketOptions& options,
433 // Try to find an entry for this specific address; we should have one.
434 TurnEntry* entry = FindEntry(addr);
435 ASSERT(entry != NULL);
441 error_ = EWOULDBLOCK;
445 // Send the actual contents to the server using the usual mechanism.
446 int sent = entry->Send(data, size, payload, options);
451 // The caller of the function is expecting the number of user data bytes,
452 // rather than the size of the packet.
453 return static_cast<int>(size);
456 void TurnPort::OnReadPacket(
457 rtc::AsyncPacketSocket* socket, const char* data, size_t size,
458 const rtc::SocketAddress& remote_addr,
459 const rtc::PacketTime& packet_time) {
460 ASSERT(socket == socket_);
461 ASSERT(remote_addr == server_address_.address);
463 // The message must be at least the size of a channel header.
464 if (size < TURN_CHANNEL_HEADER_SIZE) {
465 LOG_J(LS_WARNING, this) << "Received TURN message that was too short";
469 // Check the message type, to see if is a Channel Data message.
470 // The message will either be channel data, a TURN data indication, or
471 // a response to a previous request.
472 uint16 msg_type = rtc::GetBE16(data);
473 if (IsTurnChannelData(msg_type)) {
474 HandleChannelData(msg_type, data, size, packet_time);
475 } else if (msg_type == TURN_DATA_INDICATION) {
476 HandleDataIndication(data, size, packet_time);
478 // This must be a response for one of our requests.
479 // Check success responses, but not errors, for MESSAGE-INTEGRITY.
480 if (IsStunSuccessResponseType(msg_type) &&
481 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
482 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
483 << "message integrity, msg_type=" << msg_type;
486 request_manager_.CheckResponse(data, size);
490 void TurnPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
492 Port::OnReadyToSend();
497 // Update current server address port with the alternate server address port.
498 bool TurnPort::SetAlternateServer(const rtc::SocketAddress& address) {
499 // Check if we have seen this address before and reject if we did.
500 AttemptedServerSet::iterator iter = attempted_server_addresses_.find(address);
501 if (iter != attempted_server_addresses_.end()) {
502 LOG_J(LS_WARNING, this) << "Redirection to ["
503 << address.ToSensitiveString()
504 << "] ignored, allocation failed.";
508 // If protocol family of server address doesn't match with local, return.
509 if (!IsCompatibleAddress(address)) {
510 LOG(LS_WARNING) << "Server IP address family does not match with "
511 << "local host address family type";
515 LOG_J(LS_INFO, this) << "Redirecting from TURN server ["
516 << server_address_.address.ToSensitiveString()
517 << "] to TURN server ["
518 << address.ToSensitiveString()
520 server_address_ = ProtocolAddress(address, server_address_.proto,
521 server_address_.secure);
523 // Insert the current address to prevent redirection pingpong.
524 attempted_server_addresses_.insert(server_address_.address);
528 void TurnPort::ResolveTurnAddress(const rtc::SocketAddress& address) {
532 resolver_ = socket_factory()->CreateAsyncResolver();
533 resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
534 resolver_->Start(address);
537 void TurnPort::OnResolveResult(rtc::AsyncResolverInterface* resolver) {
538 ASSERT(resolver == resolver_);
539 // If DNS resolve is failed when trying to connect to the server using TCP,
540 // one of the reason could be due to DNS queries blocked by firewall.
541 // In such cases we will try to connect to the server with hostname, assuming
542 // socket layer will resolve the hostname through a HTTP proxy (if any).
543 if (resolver_->GetError() != 0 && server_address_.proto == PROTO_TCP) {
544 if (!CreateTurnClientSocket()) {
550 // Copy the original server address in |resolved_address|. For TLS based
551 // sockets we need hostname along with resolved address.
552 rtc::SocketAddress resolved_address = server_address_.address;
553 if (resolver_->GetError() != 0 ||
554 !resolver_->GetResolvedAddress(ip().family(), &resolved_address)) {
555 LOG_J(LS_WARNING, this) << "TURN host lookup received error "
556 << resolver_->GetError();
557 error_ = resolver_->GetError();
561 // Signal needs both resolved and unresolved address. After signal is sent
562 // we can copy resolved address back into |server_address_|.
563 SignalResolvedServerAddress(this, server_address_.address,
565 server_address_.address = resolved_address;
569 void TurnPort::OnSendStunPacket(const void* data, size_t size,
570 StunRequest* request) {
571 rtc::PacketOptions options(DefaultDscpValue());
572 if (Send(data, size, options) < 0) {
573 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
574 << socket_->GetError();
578 void TurnPort::OnStunAddress(const rtc::SocketAddress& address) {
579 // STUN Port will discover STUN candidate, as it's supplied with first TURN
581 // Why not using this address? - P2PTransportChannel will start creating
582 // connections after first candidate, which means it could start creating the
583 // connections before TURN candidate added. For that to handle, we need to
584 // supply STUN candidate from this port to UDPPort, and TurnPort should have
585 // handle to UDPPort to pass back the address.
588 void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
589 const rtc::SocketAddress& stun_address) {
591 // For relayed candidate, Base is the candidate itself.
592 AddAddress(address, // Candidate address.
593 address, // Base address.
594 stun_address, // Related address.
596 "", // TCP canddiate type, empty for turn candidates.
598 GetRelayPreference(server_address_.proto, server_address_.secure),
603 void TurnPort::OnAllocateError() {
604 // We will send SignalPortError asynchronously as this can be sent during
605 // port initialization. This way it will not be blocking other port
607 thread()->Post(this, MSG_ERROR);
610 void TurnPort::OnMessage(rtc::Message* message) {
611 if (message->message_id == MSG_ERROR) {
612 SignalPortError(this);
614 } else if (message->message_id == MSG_ALLOCATE_MISMATCH) {
615 OnAllocateMismatch();
619 Port::OnMessage(message);
622 void TurnPort::OnAllocateRequestTimeout() {
626 void TurnPort::HandleDataIndication(const char* data, size_t size,
627 const rtc::PacketTime& packet_time) {
628 // Read in the message, and process according to RFC5766, Section 10.4.
629 rtc::ByteBuffer buf(data, size);
631 if (!msg.Read(&buf)) {
632 LOG_J(LS_WARNING, this) << "Received invalid TURN data indication";
636 // Check mandatory attributes.
637 const StunAddressAttribute* addr_attr =
638 msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
640 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
641 << "in data indication.";
645 const StunByteStringAttribute* data_attr =
646 msg.GetByteString(STUN_ATTR_DATA);
648 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_DATA attribute in "
649 << "data indication.";
653 // Verify that the data came from somewhere we think we have a permission for.
654 rtc::SocketAddress ext_addr(addr_attr->GetAddress());
655 if (!HasPermission(ext_addr.ipaddr())) {
656 LOG_J(LS_WARNING, this) << "Received TURN data indication with invalid "
657 << "peer address, addr="
658 << ext_addr.ToSensitiveString();
662 DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr,
663 PROTO_UDP, packet_time);
666 void TurnPort::HandleChannelData(int channel_id, const char* data,
668 const rtc::PacketTime& packet_time) {
669 // Read the message, and process according to RFC5766, Section 11.6.
671 // 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
672 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
673 // | Channel Number | Length |
674 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676 // / Application Data /
679 // | +-------------------------------+
681 // +-------------------------------+
683 // Extract header fields from the message.
684 uint16 len = rtc::GetBE16(data + 2);
685 if (len > size - TURN_CHANNEL_HEADER_SIZE) {
686 LOG_J(LS_WARNING, this) << "Received TURN channel data message with "
687 << "incorrect length, len=" << len;
690 // Allowing messages larger than |len|, as ChannelData can be padded.
692 TurnEntry* entry = FindEntry(channel_id);
694 LOG_J(LS_WARNING, this) << "Received TURN channel data message for invalid "
695 << "channel, channel_id=" << channel_id;
699 DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
700 PROTO_UDP, packet_time);
703 void TurnPort::DispatchPacket(const char* data, size_t size,
704 const rtc::SocketAddress& remote_addr,
705 ProtocolType proto, const rtc::PacketTime& packet_time) {
706 if (Connection* conn = GetConnection(remote_addr)) {
707 conn->OnReadPacket(data, size, packet_time);
709 Port::OnReadPacket(data, size, remote_addr, proto);
713 bool TurnPort::ScheduleRefresh(int lifetime) {
714 // Lifetime is in seconds; we schedule a refresh for one minute less.
715 if (lifetime < 2 * 60) {
716 LOG_J(LS_WARNING, this) << "Received response with lifetime that was "
717 << "too short, lifetime=" << lifetime;
721 SendRequest(new TurnRefreshRequest(this), (lifetime - 60) * 1000);
725 void TurnPort::SendRequest(StunRequest* req, int delay) {
726 request_manager_.SendDelayed(req, delay);
729 void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
730 // If we've gotten the necessary data from the server, add it to our request.
731 VERIFY(!hash_.empty());
732 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
733 STUN_ATTR_USERNAME, credentials_.username)));
734 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
735 STUN_ATTR_REALM, realm_)));
736 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
737 STUN_ATTR_NONCE, nonce_)));
738 VERIFY(msg->AddMessageIntegrity(hash()));
741 int TurnPort::Send(const void* data, size_t len,
742 const rtc::PacketOptions& options) {
743 return socket_->SendTo(data, len, server_address_.address, options);
746 void TurnPort::UpdateHash() {
747 VERIFY(ComputeStunCredentialHash(credentials_.username, realm_,
748 credentials_.password, &hash_));
751 bool TurnPort::UpdateNonce(StunMessage* response) {
752 // When stale nonce error received, we should update
753 // hash and store realm and nonce.
754 // Check the mandatory attributes.
755 const StunByteStringAttribute* realm_attr =
756 response->GetByteString(STUN_ATTR_REALM);
758 LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
759 << "stale nonce error response.";
762 set_realm(realm_attr->GetString());
764 const StunByteStringAttribute* nonce_attr =
765 response->GetByteString(STUN_ATTR_NONCE);
767 LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
768 << "stale nonce error response.";
771 set_nonce(nonce_attr->GetString());
775 static bool MatchesIP(TurnEntry* e, rtc::IPAddress ipaddr) {
776 return e->address().ipaddr() == ipaddr;
778 bool TurnPort::HasPermission(const rtc::IPAddress& ipaddr) const {
779 return (std::find_if(entries_.begin(), entries_.end(),
780 std::bind2nd(std::ptr_fun(MatchesIP), ipaddr)) != entries_.end());
783 static bool MatchesAddress(TurnEntry* e, rtc::SocketAddress addr) {
784 return e->address() == addr;
786 TurnEntry* TurnPort::FindEntry(const rtc::SocketAddress& addr) const {
787 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
788 std::bind2nd(std::ptr_fun(MatchesAddress), addr));
789 return (it != entries_.end()) ? *it : NULL;
792 static bool MatchesChannelId(TurnEntry* e, int id) {
793 return e->channel_id() == id;
795 TurnEntry* TurnPort::FindEntry(int channel_id) const {
796 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
797 std::bind2nd(std::ptr_fun(MatchesChannelId), channel_id));
798 return (it != entries_.end()) ? *it : NULL;
801 TurnEntry* TurnPort::CreateEntry(const rtc::SocketAddress& addr) {
802 ASSERT(FindEntry(addr) == NULL);
803 TurnEntry* entry = new TurnEntry(this, next_channel_number_++, addr);
804 entries_.push_back(entry);
808 void TurnPort::DestroyEntry(const rtc::SocketAddress& addr) {
809 TurnEntry* entry = FindEntry(addr);
810 ASSERT(entry != NULL);
811 entry->SignalDestroyed(entry);
812 entries_.remove(entry);
816 void TurnPort::OnConnectionDestroyed(Connection* conn) {
817 // Destroying TurnEntry for the connection, which is already destroyed.
818 DestroyEntry(conn->remote_candidate().address());
821 TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
822 : StunRequest(new TurnMessage()),
826 void TurnAllocateRequest::Prepare(StunMessage* request) {
827 // Create the request as indicated in RFC 5766, Section 6.1.
828 request->SetType(TURN_ALLOCATE_REQUEST);
829 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
830 STUN_ATTR_REQUESTED_TRANSPORT);
831 transport_attr->SetValue(IPPROTO_UDP << 24);
832 VERIFY(request->AddAttribute(transport_attr));
833 if (!port_->hash().empty()) {
834 port_->AddRequestAuthInfo(request);
838 void TurnAllocateRequest::OnResponse(StunMessage* response) {
839 // Check mandatory attributes as indicated in RFC5766, Section 6.3.
840 const StunAddressAttribute* mapped_attr =
841 response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
843 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
844 << "attribute in allocate success response";
847 // Using XOR-Mapped-Address for stun.
848 port_->OnStunAddress(mapped_attr->GetAddress());
850 const StunAddressAttribute* relayed_attr =
851 response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
853 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
854 << "attribute in allocate success response";
858 const StunUInt32Attribute* lifetime_attr =
859 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
860 if (!lifetime_attr) {
861 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
862 << "allocate success response";
865 // Notify the port the allocate succeeded, and schedule a refresh request.
866 port_->OnAllocateSuccess(relayed_attr->GetAddress(),
867 mapped_attr->GetAddress());
868 port_->ScheduleRefresh(lifetime_attr->value());
871 void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
872 // Process error response according to RFC5766, Section 6.4.
873 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
874 switch (error_code->code()) {
875 case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
876 OnAuthChallenge(response, error_code->code());
878 case STUN_ERROR_TRY_ALTERNATE:
879 OnTryAlternate(response, error_code->code());
881 case STUN_ERROR_ALLOCATION_MISMATCH:
882 // We must handle this error async because trying to delete the socket in
883 // OnErrorResponse will cause a deadlock on the socket.
884 port_->thread()->Post(port_, TurnPort::MSG_ALLOCATE_MISMATCH);
887 LOG_J(LS_WARNING, port_) << "Allocate response error, code="
888 << error_code->code();
889 port_->OnAllocateError();
893 void TurnAllocateRequest::OnTimeout() {
894 LOG_J(LS_WARNING, port_) << "Allocate request timeout";
895 port_->OnAllocateRequestTimeout();
898 void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
899 // If we failed to authenticate even after we sent our credentials, fail hard.
900 if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
901 LOG_J(LS_WARNING, port_) << "Failed to authenticate with the server "
902 << "after challenge.";
903 port_->OnAllocateError();
907 // Check the mandatory attributes.
908 const StunByteStringAttribute* realm_attr =
909 response->GetByteString(STUN_ATTR_REALM);
911 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_REALM attribute in "
912 << "allocate unauthorized response.";
915 port_->set_realm(realm_attr->GetString());
917 const StunByteStringAttribute* nonce_attr =
918 response->GetByteString(STUN_ATTR_NONCE);
920 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_NONCE attribute in "
921 << "allocate unauthorized response.";
924 port_->set_nonce(nonce_attr->GetString());
926 // Send another allocate request, with the received realm and nonce values.
927 port_->SendRequest(new TurnAllocateRequest(port_), 0);
930 void TurnAllocateRequest::OnTryAlternate(StunMessage* response, int code) {
931 // TODO(guoweis): Currently, we only support UDP redirect
932 if (port_->server_address().proto != PROTO_UDP) {
933 LOG_J(LS_WARNING, port_) << "Receiving 300 Alternate Server on non-UDP "
934 << "allocating request from ["
935 << port_->server_address().address.ToSensitiveString()
936 << "], failed as currently not supported";
937 port_->OnAllocateError();
941 // According to RFC 5389 section 11, there are use cases where
942 // authentication of response is not possible, we're not validating
943 // message integrity.
945 // Get the alternate server address attribute value.
946 const StunAddressAttribute* alternate_server_attr =
947 response->GetAddress(STUN_ATTR_ALTERNATE_SERVER);
948 if (!alternate_server_attr) {
949 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_ALTERNATE_SERVER "
950 << "attribute in try alternate error response";
951 port_->OnAllocateError();
954 if (!port_->SetAlternateServer(alternate_server_attr->GetAddress())) {
955 port_->OnAllocateError();
959 // Check the attributes.
960 const StunByteStringAttribute* realm_attr =
961 response->GetByteString(STUN_ATTR_REALM);
963 LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_REALM attribute in "
964 << "try alternate error response.";
965 port_->set_realm(realm_attr->GetString());
968 const StunByteStringAttribute* nonce_attr =
969 response->GetByteString(STUN_ATTR_NONCE);
971 LOG_J(LS_INFO, port_) << "Applying STUN_ATTR_NONCE attribute in "
972 << "try alternate error response.";
973 port_->set_nonce(nonce_attr->GetString());
976 // Send another allocate request to alternate server,
977 // with the received realm and nonce values.
978 port_->SendRequest(new TurnAllocateRequest(port_), 0);
981 TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
982 : StunRequest(new TurnMessage()),
986 void TurnRefreshRequest::Prepare(StunMessage* request) {
987 // Create the request as indicated in RFC 5766, Section 7.1.
988 // No attributes need to be included.
989 request->SetType(TURN_REFRESH_REQUEST);
990 port_->AddRequestAuthInfo(request);
993 void TurnRefreshRequest::OnResponse(StunMessage* response) {
994 // Check mandatory attributes as indicated in RFC5766, Section 7.3.
995 const StunUInt32Attribute* lifetime_attr =
996 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
997 if (!lifetime_attr) {
998 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
999 << "refresh success response.";
1003 // Schedule a refresh based on the returned lifetime value.
1004 port_->ScheduleRefresh(lifetime_attr->value());
1007 void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
1008 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1009 LOG_J(LS_WARNING, port_) << "Refresh response error, code="
1010 << error_code->code();
1012 if (error_code->code() == STUN_ERROR_STALE_NONCE) {
1013 if (port_->UpdateNonce(response)) {
1014 // Send RefreshRequest immediately.
1015 port_->SendRequest(new TurnRefreshRequest(port_), 0);
1020 void TurnRefreshRequest::OnTimeout() {
1023 TurnCreatePermissionRequest::TurnCreatePermissionRequest(
1024 TurnPort* port, TurnEntry* entry,
1025 const rtc::SocketAddress& ext_addr)
1026 : StunRequest(new TurnMessage()),
1029 ext_addr_(ext_addr) {
1030 entry_->SignalDestroyed.connect(
1031 this, &TurnCreatePermissionRequest::OnEntryDestroyed);
1034 void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
1035 // Create the request as indicated in RFC5766, Section 9.1.
1036 request->SetType(TURN_CREATE_PERMISSION_REQUEST);
1037 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
1038 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1039 port_->AddRequestAuthInfo(request);
1042 void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
1044 entry_->OnCreatePermissionSuccess();
1048 void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
1050 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1051 entry_->OnCreatePermissionError(response, error_code->code());
1055 void TurnCreatePermissionRequest::OnTimeout() {
1056 LOG_J(LS_WARNING, port_) << "Create permission timeout";
1059 void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
1060 ASSERT(entry_ == entry);
1064 TurnChannelBindRequest::TurnChannelBindRequest(
1065 TurnPort* port, TurnEntry* entry,
1066 int channel_id, const rtc::SocketAddress& ext_addr)
1067 : StunRequest(new TurnMessage()),
1070 channel_id_(channel_id),
1071 ext_addr_(ext_addr) {
1072 entry_->SignalDestroyed.connect(
1073 this, &TurnChannelBindRequest::OnEntryDestroyed);
1076 void TurnChannelBindRequest::Prepare(StunMessage* request) {
1077 // Create the request as indicated in RFC5766, Section 11.1.
1078 request->SetType(TURN_CHANNEL_BIND_REQUEST);
1079 VERIFY(request->AddAttribute(new StunUInt32Attribute(
1080 STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16)));
1081 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
1082 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1083 port_->AddRequestAuthInfo(request);
1086 void TurnChannelBindRequest::OnResponse(StunMessage* response) {
1088 entry_->OnChannelBindSuccess();
1089 // Refresh the channel binding just under the permission timeout
1090 // threshold. The channel binding has a longer lifetime, but
1091 // this is the easiest way to keep both the channel and the
1092 // permission from expiring.
1093 entry_->SendChannelBindRequest(TURN_PERMISSION_TIMEOUT - 60 * 1000);
1097 void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
1099 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
1100 entry_->OnChannelBindError(response, error_code->code());
1104 void TurnChannelBindRequest::OnTimeout() {
1105 LOG_J(LS_WARNING, port_) << "Channel bind timeout";
1108 void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
1109 ASSERT(entry_ == entry);
1113 TurnEntry::TurnEntry(TurnPort* port, int channel_id,
1114 const rtc::SocketAddress& ext_addr)
1116 channel_id_(channel_id),
1117 ext_addr_(ext_addr),
1118 state_(STATE_UNBOUND) {
1119 // Creating permission for |ext_addr_|.
1120 SendCreatePermissionRequest();
1123 void TurnEntry::SendCreatePermissionRequest() {
1124 port_->SendRequest(new TurnCreatePermissionRequest(
1125 port_, this, ext_addr_), 0);
1128 void TurnEntry::SendChannelBindRequest(int delay) {
1129 port_->SendRequest(new TurnChannelBindRequest(
1130 port_, this, channel_id_, ext_addr_), delay);
1133 int TurnEntry::Send(const void* data, size_t size, bool payload,
1134 const rtc::PacketOptions& options) {
1135 rtc::ByteBuffer buf;
1136 if (state_ != STATE_BOUND) {
1137 // If we haven't bound the channel yet, we have to use a Send Indication.
1139 msg.SetType(TURN_SEND_INDICATION);
1140 msg.SetTransactionID(
1141 rtc::CreateRandomString(kStunTransactionIdLength));
1142 VERIFY(msg.AddAttribute(new StunXorAddressAttribute(
1143 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
1144 VERIFY(msg.AddAttribute(new StunByteStringAttribute(
1145 STUN_ATTR_DATA, data, size)));
1146 VERIFY(msg.Write(&buf));
1148 // If we're sending real data, request a channel bind that we can use later.
1149 if (state_ == STATE_UNBOUND && payload) {
1150 SendChannelBindRequest(0);
1151 state_ = STATE_BINDING;
1154 // If the channel is bound, we can send the data as a Channel Message.
1155 buf.WriteUInt16(channel_id_);
1156 buf.WriteUInt16(static_cast<uint16>(size));
1157 buf.WriteBytes(reinterpret_cast<const char*>(data), size);
1159 return port_->Send(buf.Data(), buf.Length(), options);
1162 void TurnEntry::OnCreatePermissionSuccess() {
1163 LOG_J(LS_INFO, port_) << "Create permission for "
1164 << ext_addr_.ToSensitiveString()
1166 // For success result code will be 0.
1167 port_->SignalCreatePermissionResult(port_, ext_addr_, 0);
1170 void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
1171 LOG_J(LS_WARNING, port_) << "Create permission for "
1172 << ext_addr_.ToSensitiveString()
1173 << " failed, code=" << code;
1174 if (code == STUN_ERROR_STALE_NONCE) {
1175 if (port_->UpdateNonce(response)) {
1176 SendCreatePermissionRequest();
1179 // Send signal with error code.
1180 port_->SignalCreatePermissionResult(port_, ext_addr_, code);
1184 void TurnEntry::OnChannelBindSuccess() {
1185 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString()
1187 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND);
1188 state_ = STATE_BOUND;
1191 void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1192 // TODO(mallinath) - Implement handling of error response for channel
1193 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
1194 LOG_J(LS_WARNING, port_) << "Channel bind for "
1195 << ext_addr_.ToSensitiveString()
1196 << " failed, code=" << code;
1197 if (code == STUN_ERROR_STALE_NONCE) {
1198 if (port_->UpdateNonce(response)) {
1199 // Send channel bind request with fresh nonce.
1200 SendChannelBindRequest(0);
1205 } // namespace cricket