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/base/asyncpacketsocket.h"
33 #include "talk/base/byteorder.h"
34 #include "talk/base/common.h"
35 #include "talk/base/logging.h"
36 #include "talk/base/nethelpers.h"
37 #include "talk/base/socketaddress.h"
38 #include "talk/base/stringencode.h"
39 #include "talk/p2p/base/common.h"
40 #include "talk/p2p/base/stun.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 inline bool IsTurnChannelData(uint16 msg_type) {
55 return ((msg_type & 0xC000) == 0x4000); // MSB are 0b01
58 static int GetRelayPreference(cricket::ProtocolType proto, bool secure) {
59 int relay_preference = ICE_TYPE_PREFERENCE_RELAY;
60 if (proto == cricket::PROTO_TCP) {
61 relay_preference -= 1;
63 relay_preference -= 1;
66 ASSERT(relay_preference >= 0);
67 return relay_preference;
70 class TurnAllocateRequest : public StunRequest {
72 explicit TurnAllocateRequest(TurnPort* port);
73 virtual void Prepare(StunMessage* request);
74 virtual void OnResponse(StunMessage* response);
75 virtual void OnErrorResponse(StunMessage* response);
76 virtual void OnTimeout();
79 // Handles authentication challenge from the server.
80 void OnAuthChallenge(StunMessage* response, int code);
81 void OnUnknownAttribute(StunMessage* response);
86 class TurnRefreshRequest : public StunRequest {
88 explicit TurnRefreshRequest(TurnPort* port);
89 virtual void Prepare(StunMessage* request);
90 virtual void OnResponse(StunMessage* response);
91 virtual void OnErrorResponse(StunMessage* response);
92 virtual void OnTimeout();
98 class TurnCreatePermissionRequest : public StunRequest,
99 public sigslot::has_slots<> {
101 TurnCreatePermissionRequest(TurnPort* port, TurnEntry* entry,
102 const talk_base::SocketAddress& ext_addr);
103 virtual void Prepare(StunMessage* request);
104 virtual void OnResponse(StunMessage* response);
105 virtual void OnErrorResponse(StunMessage* response);
106 virtual void OnTimeout();
109 void OnEntryDestroyed(TurnEntry* entry);
113 talk_base::SocketAddress ext_addr_;
116 class TurnChannelBindRequest : public StunRequest,
117 public sigslot::has_slots<> {
119 TurnChannelBindRequest(TurnPort* port, TurnEntry* entry, int channel_id,
120 const talk_base::SocketAddress& ext_addr);
121 virtual void Prepare(StunMessage* request);
122 virtual void OnResponse(StunMessage* response);
123 virtual void OnErrorResponse(StunMessage* response);
124 virtual void OnTimeout();
127 void OnEntryDestroyed(TurnEntry* entry);
132 talk_base::SocketAddress ext_addr_;
135 // Manages a "connection" to a remote destination. We will attempt to bring up
136 // a channel for this remote destination to reduce the overhead of sending data.
137 class TurnEntry : public sigslot::has_slots<> {
139 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
140 TurnEntry(TurnPort* port, int channel_id,
141 const talk_base::SocketAddress& ext_addr);
143 TurnPort* port() { return port_; }
145 int channel_id() const { return channel_id_; }
146 const talk_base::SocketAddress& address() const { return ext_addr_; }
147 BindState state() const { return state_; }
149 // Helper methods to send permission and channel bind requests.
150 void SendCreatePermissionRequest();
151 void SendChannelBindRequest(int delay);
152 // Sends a packet to the given destination address.
153 // This will wrap the packet in STUN if necessary.
154 int Send(const void* data, size_t size, bool payload,
155 const talk_base::PacketOptions& options);
157 void OnCreatePermissionSuccess();
158 void OnCreatePermissionError(StunMessage* response, int code);
159 void OnChannelBindSuccess();
160 void OnChannelBindError(StunMessage* response, int code);
161 // Signal sent when TurnEntry is destroyed.
162 sigslot::signal1<TurnEntry*> SignalDestroyed;
167 talk_base::SocketAddress ext_addr_;
171 TurnPort::TurnPort(talk_base::Thread* thread,
172 talk_base::PacketSocketFactory* factory,
173 talk_base::Network* network,
174 talk_base::AsyncPacketSocket* socket,
175 const std::string& username,
176 const std::string& password,
177 const ProtocolAddress& server_address,
178 const RelayCredentials& credentials)
179 : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
181 server_address_(server_address),
182 credentials_(credentials),
186 request_manager_(thread),
187 next_channel_number_(TURN_CHANNEL_NUMBER_START),
189 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
192 TurnPort::TurnPort(talk_base::Thread* thread,
193 talk_base::PacketSocketFactory* factory,
194 talk_base::Network* network,
195 const talk_base::IPAddress& ip,
196 int min_port, int max_port,
197 const std::string& username,
198 const std::string& password,
199 const ProtocolAddress& server_address,
200 const RelayCredentials& credentials)
201 : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port,
203 server_address_(server_address),
204 credentials_(credentials),
208 request_manager_(thread),
209 next_channel_number_(TURN_CHANNEL_NUMBER_START),
211 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
214 TurnPort::~TurnPort() {
215 // TODO(juberti): Should this even be necessary?
216 while (!entries_.empty()) {
217 DestroyEntry(entries_.front()->address());
220 resolver_->Destroy(false);
222 if (!SharedSocket()) {
227 void TurnPort::PrepareAddress() {
228 if (credentials_.username.empty() ||
229 credentials_.password.empty()) {
230 LOG(LS_ERROR) << "Allocation can't be started without setting the"
231 << " TURN server credentials for the user.";
236 if (!server_address_.address.port()) {
237 // We will set default TURN port, if no port is set in the address.
238 server_address_.address.SetPort(TURN_DEFAULT_PORT);
241 if (server_address_.address.IsUnresolved()) {
242 ResolveTurnAddress(server_address_.address);
244 // If protocol family of server address doesn't match with local, return.
245 if (!IsCompatibleAddress(server_address_.address)) {
246 LOG(LS_ERROR) << "Server IP address family does not match with "
247 << "local host address family type";
252 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
253 << ProtoToString(server_address_.proto) << " @ "
254 << server_address_.address.ToSensitiveString();
255 if (server_address_.proto == PROTO_UDP && !SharedSocket()) {
256 socket_ = socket_factory()->CreateUdpSocket(
257 talk_base::SocketAddress(ip(), 0), min_port(), max_port());
258 } else if (server_address_.proto == PROTO_TCP) {
259 ASSERT(!SharedSocket());
260 int opts = talk_base::PacketSocketFactory::OPT_STUN;
261 // If secure bit is enabled in server address, use TLS over TCP.
262 if (server_address_.secure) {
263 opts |= talk_base::PacketSocketFactory::OPT_TLS;
265 socket_ = socket_factory()->CreateClientTcpSocket(
266 talk_base::SocketAddress(ip(), 0), server_address_.address,
267 proxy(), user_agent(), opts);
275 // Apply options if any.
276 for (SocketOptionsMap::iterator iter = socket_options_.begin();
277 iter != socket_options_.end(); ++iter) {
278 socket_->SetOption(iter->first, iter->second);
281 if (!SharedSocket()) {
282 // If socket is shared, AllocationSequence will receive the packet.
283 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
286 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
288 if (server_address_.proto == PROTO_TCP) {
289 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
290 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
292 // If its UDP, send AllocateRequest now.
293 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
294 SendRequest(new TurnAllocateRequest(this), 0);
299 void TurnPort::OnSocketConnect(talk_base::AsyncPacketSocket* socket) {
300 ASSERT(server_address_.proto == PROTO_TCP);
301 // Do not use this port if the socket bound to a different address than
302 // the one we asked for. This is seen in Chrome, where TCP sockets cannot be
303 // given a binding address, and the platform is expected to pick the
304 // correct local address.
305 if (socket->GetLocalAddress().ipaddr() != ip()) {
306 LOG(LS_WARNING) << "Socket is bound to a different address then the "
307 << "local port. Discarding TURN port.";
312 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
314 SendRequest(new TurnAllocateRequest(this), 0);
317 void TurnPort::OnSocketClose(talk_base::AsyncPacketSocket* socket, int error) {
318 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
324 Connection* TurnPort::CreateConnection(const Candidate& address,
325 CandidateOrigin origin) {
326 // TURN-UDP can only connect to UDP candidates.
327 if (address.protocol() != UDP_PROTOCOL_NAME) {
331 if (!IsCompatibleAddress(address.address())) {
335 // Create an entry, if needed, so we can get our permissions set up correctly.
336 CreateEntry(address.address());
338 // A TURN port will have two candiates, STUN and TURN. STUN may not
339 // present in all cases. If present stun candidate will be added first
340 // and TURN candidate later.
341 for (size_t index = 0; index < Candidates().size(); ++index) {
342 if (Candidates()[index].type() == RELAY_PORT_TYPE) {
343 ProxyConnection* conn = new ProxyConnection(this, index, address);
344 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
352 int TurnPort::SetOption(talk_base::Socket::Option opt, int value) {
354 // If socket is not created yet, these options will be applied during socket
356 socket_options_[opt] = value;
359 return socket_->SetOption(opt, value);
362 int TurnPort::GetOption(talk_base::Socket::Option opt, int* value) {
364 SocketOptionsMap::const_iterator it = socket_options_.find(opt);
365 if (it == socket_options_.end()) {
372 return socket_->GetOption(opt, value);
375 int TurnPort::GetError() {
379 int TurnPort::SendTo(const void* data, size_t size,
380 const talk_base::SocketAddress& addr,
381 const talk_base::PacketOptions& options,
383 // Try to find an entry for this specific address; we should have one.
384 TurnEntry* entry = FindEntry(addr);
385 ASSERT(entry != NULL);
391 error_ = EWOULDBLOCK;
395 // Send the actual contents to the server using the usual mechanism.
396 int sent = entry->Send(data, size, payload, options);
401 // The caller of the function is expecting the number of user data bytes,
402 // rather than the size of the packet.
403 return static_cast<int>(size);
406 void TurnPort::OnReadPacket(
407 talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
408 const talk_base::SocketAddress& remote_addr,
409 const talk_base::PacketTime& packet_time) {
410 ASSERT(socket == socket_);
411 ASSERT(remote_addr == server_address_.address);
413 // The message must be at least the size of a channel header.
414 if (size < TURN_CHANNEL_HEADER_SIZE) {
415 LOG_J(LS_WARNING, this) << "Received TURN message that was too short";
419 // Check the message type, to see if is a Channel Data message.
420 // The message will either be channel data, a TURN data indication, or
421 // a response to a previous request.
422 uint16 msg_type = talk_base::GetBE16(data);
423 if (IsTurnChannelData(msg_type)) {
424 HandleChannelData(msg_type, data, size, packet_time);
425 } else if (msg_type == TURN_DATA_INDICATION) {
426 HandleDataIndication(data, size, packet_time);
428 // This must be a response for one of our requests.
429 // Check success responses, but not errors, for MESSAGE-INTEGRITY.
430 if (IsStunSuccessResponseType(msg_type) &&
431 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
432 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
433 << "message integrity, msg_type=" << msg_type;
436 request_manager_.CheckResponse(data, size);
440 void TurnPort::OnReadyToSend(talk_base::AsyncPacketSocket* socket) {
442 Port::OnReadyToSend();
446 void TurnPort::ResolveTurnAddress(const talk_base::SocketAddress& address) {
450 resolver_ = socket_factory()->CreateAsyncResolver();
451 resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
452 resolver_->Start(address);
455 void TurnPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
456 ASSERT(resolver == resolver_);
457 // Copy the original server address in |resolved_address|. For TLS based
458 // sockets we need hostname along with resolved address.
459 talk_base::SocketAddress resolved_address = server_address_.address;
460 if (resolver_->GetError() != 0 ||
461 !resolver_->GetResolvedAddress(ip().family(), &resolved_address)) {
462 LOG_J(LS_WARNING, this) << "TURN host lookup received error "
463 << resolver_->GetError();
467 // Signal needs both resolved and unresolved address. After signal is sent
468 // we can copy resolved address back into |server_address_|.
469 SignalResolvedServerAddress(this, server_address_.address,
471 server_address_.address = resolved_address;
475 void TurnPort::OnSendStunPacket(const void* data, size_t size,
476 StunRequest* request) {
477 talk_base::PacketOptions options(DefaultDscpValue());
478 if (Send(data, size, options) < 0) {
479 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
480 << socket_->GetError();
484 void TurnPort::OnStunAddress(const talk_base::SocketAddress& address) {
485 // STUN Port will discover STUN candidate, as it's supplied with first TURN
487 // Why not using this address? - P2PTransportChannel will start creating
488 // connections after first candidate, which means it could start creating the
489 // connections before TURN candidate added. For that to handle, we need to
490 // supply STUN candidate from this port to UDPPort, and TurnPort should have
491 // handle to UDPPort to pass back the address.
494 void TurnPort::OnAllocateSuccess(const talk_base::SocketAddress& address,
495 const talk_base::SocketAddress& stun_address) {
497 // For relayed candidate, Base is the candidate itself.
498 AddAddress(address, // Candidate address.
499 address, // Base address.
500 stun_address, // Related address.
503 GetRelayPreference(server_address_.proto, server_address_.secure),
507 void TurnPort::OnAllocateError() {
508 // We will send SignalPortError asynchronously as this can be sent during
509 // port initialization. This way it will not be blocking other port
511 thread()->Post(this, MSG_ERROR);
514 void TurnPort::OnMessage(talk_base::Message* message) {
515 if (message->message_id == MSG_ERROR) {
516 SignalPortError(this);
520 Port::OnMessage(message);
523 void TurnPort::OnAllocateRequestTimeout() {
527 void TurnPort::HandleDataIndication(const char* data, size_t size,
528 const talk_base::PacketTime& packet_time) {
529 // Read in the message, and process according to RFC5766, Section 10.4.
530 talk_base::ByteBuffer buf(data, size);
532 if (!msg.Read(&buf)) {
533 LOG_J(LS_WARNING, this) << "Received invalid TURN data indication";
537 // Check mandatory attributes.
538 const StunAddressAttribute* addr_attr =
539 msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
541 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
542 << "in data indication.";
546 const StunByteStringAttribute* data_attr =
547 msg.GetByteString(STUN_ATTR_DATA);
549 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_DATA attribute in "
550 << "data indication.";
554 // Verify that the data came from somewhere we think we have a permission for.
555 talk_base::SocketAddress ext_addr(addr_attr->GetAddress());
556 if (!HasPermission(ext_addr.ipaddr())) {
557 LOG_J(LS_WARNING, this) << "Received TURN data indication with invalid "
558 << "peer address, addr="
559 << ext_addr.ToSensitiveString();
563 DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr,
564 PROTO_UDP, packet_time);
567 void TurnPort::HandleChannelData(int channel_id, const char* data,
569 const talk_base::PacketTime& packet_time) {
570 // Read the message, and process according to RFC5766, Section 11.6.
572 // 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
573 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574 // | Channel Number | Length |
575 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
577 // / Application Data /
580 // | +-------------------------------+
582 // +-------------------------------+
584 // Extract header fields from the message.
585 uint16 len = talk_base::GetBE16(data + 2);
586 if (len > size - TURN_CHANNEL_HEADER_SIZE) {
587 LOG_J(LS_WARNING, this) << "Received TURN channel data message with "
588 << "incorrect length, len=" << len;
591 // Allowing messages larger than |len|, as ChannelData can be padded.
593 TurnEntry* entry = FindEntry(channel_id);
595 LOG_J(LS_WARNING, this) << "Received TURN channel data message for invalid "
596 << "channel, channel_id=" << channel_id;
600 DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
601 PROTO_UDP, packet_time);
604 void TurnPort::DispatchPacket(const char* data, size_t size,
605 const talk_base::SocketAddress& remote_addr,
606 ProtocolType proto, const talk_base::PacketTime& packet_time) {
607 if (Connection* conn = GetConnection(remote_addr)) {
608 conn->OnReadPacket(data, size, packet_time);
610 Port::OnReadPacket(data, size, remote_addr, proto);
614 bool TurnPort::ScheduleRefresh(int lifetime) {
615 // Lifetime is in seconds; we schedule a refresh for one minute less.
616 if (lifetime < 2 * 60) {
617 LOG_J(LS_WARNING, this) << "Received response with lifetime that was "
618 << "too short, lifetime=" << lifetime;
622 SendRequest(new TurnRefreshRequest(this), (lifetime - 60) * 1000);
626 void TurnPort::SendRequest(StunRequest* req, int delay) {
627 request_manager_.SendDelayed(req, delay);
630 void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
631 // If we've gotten the necessary data from the server, add it to our request.
632 VERIFY(!hash_.empty());
633 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
634 STUN_ATTR_USERNAME, credentials_.username)));
635 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
636 STUN_ATTR_REALM, realm_)));
637 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
638 STUN_ATTR_NONCE, nonce_)));
639 VERIFY(msg->AddMessageIntegrity(hash()));
642 int TurnPort::Send(const void* data, size_t len,
643 const talk_base::PacketOptions& options) {
644 return socket_->SendTo(data, len, server_address_.address, options);
647 void TurnPort::UpdateHash() {
648 VERIFY(ComputeStunCredentialHash(credentials_.username, realm_,
649 credentials_.password, &hash_));
652 bool TurnPort::UpdateNonce(StunMessage* response) {
653 // When stale nonce error received, we should update
654 // hash and store realm and nonce.
655 // Check the mandatory attributes.
656 const StunByteStringAttribute* realm_attr =
657 response->GetByteString(STUN_ATTR_REALM);
659 LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
660 << "stale nonce error response.";
663 set_realm(realm_attr->GetString());
665 const StunByteStringAttribute* nonce_attr =
666 response->GetByteString(STUN_ATTR_NONCE);
668 LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
669 << "stale nonce error response.";
672 set_nonce(nonce_attr->GetString());
676 static bool MatchesIP(TurnEntry* e, talk_base::IPAddress ipaddr) {
677 return e->address().ipaddr() == ipaddr;
679 bool TurnPort::HasPermission(const talk_base::IPAddress& ipaddr) const {
680 return (std::find_if(entries_.begin(), entries_.end(),
681 std::bind2nd(std::ptr_fun(MatchesIP), ipaddr)) != entries_.end());
684 static bool MatchesAddress(TurnEntry* e, talk_base::SocketAddress addr) {
685 return e->address() == addr;
687 TurnEntry* TurnPort::FindEntry(const talk_base::SocketAddress& addr) const {
688 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
689 std::bind2nd(std::ptr_fun(MatchesAddress), addr));
690 return (it != entries_.end()) ? *it : NULL;
693 static bool MatchesChannelId(TurnEntry* e, int id) {
694 return e->channel_id() == id;
696 TurnEntry* TurnPort::FindEntry(int channel_id) const {
697 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
698 std::bind2nd(std::ptr_fun(MatchesChannelId), channel_id));
699 return (it != entries_.end()) ? *it : NULL;
702 TurnEntry* TurnPort::CreateEntry(const talk_base::SocketAddress& addr) {
703 ASSERT(FindEntry(addr) == NULL);
704 TurnEntry* entry = new TurnEntry(this, next_channel_number_++, addr);
705 entries_.push_back(entry);
709 void TurnPort::DestroyEntry(const talk_base::SocketAddress& addr) {
710 TurnEntry* entry = FindEntry(addr);
711 ASSERT(entry != NULL);
712 entry->SignalDestroyed(entry);
713 entries_.remove(entry);
717 void TurnPort::OnConnectionDestroyed(Connection* conn) {
718 // Destroying TurnEntry for the connection, which is already destroyed.
719 DestroyEntry(conn->remote_candidate().address());
722 TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
723 : StunRequest(new TurnMessage()),
727 void TurnAllocateRequest::Prepare(StunMessage* request) {
728 // Create the request as indicated in RFC 5766, Section 6.1.
729 request->SetType(TURN_ALLOCATE_REQUEST);
730 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
731 STUN_ATTR_REQUESTED_TRANSPORT);
732 transport_attr->SetValue(IPPROTO_UDP << 24);
733 VERIFY(request->AddAttribute(transport_attr));
734 if (!port_->hash().empty()) {
735 port_->AddRequestAuthInfo(request);
739 void TurnAllocateRequest::OnResponse(StunMessage* response) {
740 // Check mandatory attributes as indicated in RFC5766, Section 6.3.
741 const StunAddressAttribute* mapped_attr =
742 response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
744 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
745 << "attribute in allocate success response";
748 // Using XOR-Mapped-Address for stun.
749 port_->OnStunAddress(mapped_attr->GetAddress());
751 const StunAddressAttribute* relayed_attr =
752 response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
754 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
755 << "attribute in allocate success response";
759 const StunUInt32Attribute* lifetime_attr =
760 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
761 if (!lifetime_attr) {
762 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
763 << "allocate success response";
766 // Notify the port the allocate succeeded, and schedule a refresh request.
767 port_->OnAllocateSuccess(relayed_attr->GetAddress(),
768 mapped_attr->GetAddress());
769 port_->ScheduleRefresh(lifetime_attr->value());
772 void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
773 // Process error response according to RFC5766, Section 6.4.
774 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
775 switch (error_code->code()) {
776 case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
777 OnAuthChallenge(response, error_code->code());
780 LOG_J(LS_WARNING, port_) << "Allocate response error, code="
781 << error_code->code();
782 port_->OnAllocateError();
786 void TurnAllocateRequest::OnTimeout() {
787 LOG_J(LS_WARNING, port_) << "Allocate request timeout";
788 port_->OnAllocateRequestTimeout();
791 void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
792 // If we failed to authenticate even after we sent our credentials, fail hard.
793 if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
794 LOG_J(LS_WARNING, port_) << "Failed to authenticate with the server "
795 << "after challenge.";
796 port_->OnAllocateError();
800 // Check the mandatory attributes.
801 const StunByteStringAttribute* realm_attr =
802 response->GetByteString(STUN_ATTR_REALM);
804 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_REALM attribute in "
805 << "allocate unauthorized response.";
808 port_->set_realm(realm_attr->GetString());
810 const StunByteStringAttribute* nonce_attr =
811 response->GetByteString(STUN_ATTR_NONCE);
813 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_NONCE attribute in "
814 << "allocate unauthorized response.";
817 port_->set_nonce(nonce_attr->GetString());
819 // Send another allocate request, with the received realm and nonce values.
820 port_->SendRequest(new TurnAllocateRequest(port_), 0);
823 TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
824 : StunRequest(new TurnMessage()),
828 void TurnRefreshRequest::Prepare(StunMessage* request) {
829 // Create the request as indicated in RFC 5766, Section 7.1.
830 // No attributes need to be included.
831 request->SetType(TURN_REFRESH_REQUEST);
832 port_->AddRequestAuthInfo(request);
835 void TurnRefreshRequest::OnResponse(StunMessage* response) {
836 // Check mandatory attributes as indicated in RFC5766, Section 7.3.
837 const StunUInt32Attribute* lifetime_attr =
838 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
839 if (!lifetime_attr) {
840 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
841 << "refresh success response.";
845 // Schedule a refresh based on the returned lifetime value.
846 port_->ScheduleRefresh(lifetime_attr->value());
849 void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
850 // TODO(juberti): Handle 437 error response as a success.
851 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
852 LOG_J(LS_WARNING, port_) << "Refresh response error, code="
853 << error_code->code();
855 if (error_code->code() == STUN_ERROR_STALE_NONCE) {
856 if (port_->UpdateNonce(response)) {
857 // Send RefreshRequest immediately.
858 port_->SendRequest(new TurnRefreshRequest(port_), 0);
863 void TurnRefreshRequest::OnTimeout() {
866 TurnCreatePermissionRequest::TurnCreatePermissionRequest(
867 TurnPort* port, TurnEntry* entry,
868 const talk_base::SocketAddress& ext_addr)
869 : StunRequest(new TurnMessage()),
872 ext_addr_(ext_addr) {
873 entry_->SignalDestroyed.connect(
874 this, &TurnCreatePermissionRequest::OnEntryDestroyed);
877 void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
878 // Create the request as indicated in RFC5766, Section 9.1.
879 request->SetType(TURN_CREATE_PERMISSION_REQUEST);
880 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
881 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
882 port_->AddRequestAuthInfo(request);
885 void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
887 entry_->OnCreatePermissionSuccess();
891 void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
893 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
894 entry_->OnCreatePermissionError(response, error_code->code());
898 void TurnCreatePermissionRequest::OnTimeout() {
899 LOG_J(LS_WARNING, port_) << "Create permission timeout";
902 void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
903 ASSERT(entry_ == entry);
907 TurnChannelBindRequest::TurnChannelBindRequest(
908 TurnPort* port, TurnEntry* entry,
909 int channel_id, const talk_base::SocketAddress& ext_addr)
910 : StunRequest(new TurnMessage()),
913 channel_id_(channel_id),
914 ext_addr_(ext_addr) {
915 entry_->SignalDestroyed.connect(
916 this, &TurnChannelBindRequest::OnEntryDestroyed);
919 void TurnChannelBindRequest::Prepare(StunMessage* request) {
920 // Create the request as indicated in RFC5766, Section 11.1.
921 request->SetType(TURN_CHANNEL_BIND_REQUEST);
922 VERIFY(request->AddAttribute(new StunUInt32Attribute(
923 STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16)));
924 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
925 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
926 port_->AddRequestAuthInfo(request);
929 void TurnChannelBindRequest::OnResponse(StunMessage* response) {
931 entry_->OnChannelBindSuccess();
932 // Refresh the channel binding just under the permission timeout
933 // threshold. The channel binding has a longer lifetime, but
934 // this is the easiest way to keep both the channel and the
935 // permission from expiring.
936 entry_->SendChannelBindRequest(TURN_PERMISSION_TIMEOUT - 60 * 1000);
940 void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
942 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
943 entry_->OnChannelBindError(response, error_code->code());
947 void TurnChannelBindRequest::OnTimeout() {
948 LOG_J(LS_WARNING, port_) << "Channel bind timeout";
951 void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
952 ASSERT(entry_ == entry);
956 TurnEntry::TurnEntry(TurnPort* port, int channel_id,
957 const talk_base::SocketAddress& ext_addr)
959 channel_id_(channel_id),
961 state_(STATE_UNBOUND) {
962 // Creating permission for |ext_addr_|.
963 SendCreatePermissionRequest();
966 void TurnEntry::SendCreatePermissionRequest() {
967 port_->SendRequest(new TurnCreatePermissionRequest(
968 port_, this, ext_addr_), 0);
971 void TurnEntry::SendChannelBindRequest(int delay) {
972 port_->SendRequest(new TurnChannelBindRequest(
973 port_, this, channel_id_, ext_addr_), delay);
976 int TurnEntry::Send(const void* data, size_t size, bool payload,
977 const talk_base::PacketOptions& options) {
978 talk_base::ByteBuffer buf;
979 if (state_ != STATE_BOUND) {
980 // If we haven't bound the channel yet, we have to use a Send Indication.
982 msg.SetType(TURN_SEND_INDICATION);
983 msg.SetTransactionID(
984 talk_base::CreateRandomString(kStunTransactionIdLength));
985 VERIFY(msg.AddAttribute(new StunXorAddressAttribute(
986 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
987 VERIFY(msg.AddAttribute(new StunByteStringAttribute(
988 STUN_ATTR_DATA, data, size)));
989 VERIFY(msg.Write(&buf));
991 // If we're sending real data, request a channel bind that we can use later.
992 if (state_ == STATE_UNBOUND && payload) {
993 SendChannelBindRequest(0);
994 state_ = STATE_BINDING;
997 // If the channel is bound, we can send the data as a Channel Message.
998 buf.WriteUInt16(channel_id_);
999 buf.WriteUInt16(static_cast<uint16>(size));
1000 buf.WriteBytes(reinterpret_cast<const char*>(data), size);
1002 return port_->Send(buf.Data(), buf.Length(), options);
1005 void TurnEntry::OnCreatePermissionSuccess() {
1006 LOG_J(LS_INFO, port_) << "Create permission for "
1007 << ext_addr_.ToSensitiveString()
1009 // For success result code will be 0.
1010 port_->SignalCreatePermissionResult(port_, ext_addr_, 0);
1013 void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
1014 LOG_J(LS_WARNING, port_) << "Create permission for "
1015 << ext_addr_.ToSensitiveString()
1016 << " failed, code=" << code;
1017 if (code == STUN_ERROR_STALE_NONCE) {
1018 if (port_->UpdateNonce(response)) {
1019 SendCreatePermissionRequest();
1022 // Send signal with error code.
1023 port_->SignalCreatePermissionResult(port_, ext_addr_, code);
1027 void TurnEntry::OnChannelBindSuccess() {
1028 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString()
1030 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND);
1031 state_ = STATE_BOUND;
1034 void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
1035 // TODO(mallinath) - Implement handling of error response for channel
1036 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
1037 LOG_J(LS_WARNING, port_) << "Channel bind for "
1038 << ext_addr_.ToSensitiveString()
1039 << " failed, code=" << code;
1040 if (code == STUN_ERROR_STALE_NONCE) {
1041 if (port_->UpdateNonce(response)) {
1042 // Send channel bind request with fresh nonce.
1043 SendChannelBindRequest(0);
1048 } // namespace cricket