1 /*
2 * libjingle
3 * Copyright 2012, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
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.
15 *
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.
26 */
27
28 #include "talk/p2p/base/turnport.h"
29
30 #include <functional>
31
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"
41
42 namespace cricket {
43
44 // TODO(juberti): Move to stun.h when relay messages have been renamed.
45 static const int TURN_ALLOCATE_REQUEST = STUN_ALLOCATE_REQUEST;
46 static const int TURN_ALLOCATE_ERROR_RESPONSE = STUN_ALLOCATE_ERROR_RESPONSE;
47
48 // TODO(juberti): Extract to turnmessage.h
49 static const int TURN_DEFAULT_PORT = 3478;
50 static const int TURN_CHANNEL_NUMBER_START = 0x4000;
51 static const int TURN_PERMISSION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
52
53 static const size_t TURN_CHANNEL_HEADER_SIZE = 4U;
54
IsTurnChannelData(uint16 msg_type)55 inline bool IsTurnChannelData(uint16 msg_type) {
56 return ((msg_type & 0xC000) == 0x4000); // MSB are 0b01
57 }
58
GetRelayPreference(cricket::ProtocolType proto,bool secure)59 static int GetRelayPreference(cricket::ProtocolType proto, bool secure) {
60 int relay_preference = ICE_TYPE_PREFERENCE_RELAY;
61 if (proto == cricket::PROTO_TCP) {
62 relay_preference -= 1;
63 if (secure)
64 relay_preference -= 1;
65 }
66
67 ASSERT(relay_preference >= 0);
68 return relay_preference;
69 }
70
71 class TurnAllocateRequest : public StunRequest {
72 public:
73 explicit TurnAllocateRequest(TurnPort* port);
74 virtual void Prepare(StunMessage* request);
75 virtual void OnResponse(StunMessage* response);
76 virtual void OnErrorResponse(StunMessage* response);
77 virtual void OnTimeout();
78
79 private:
80 // Handles authentication challenge from the server.
81 void OnAuthChallenge(StunMessage* response, int code);
82 void OnUnknownAttribute(StunMessage* response);
83
84 TurnPort* port_;
85 };
86
87 class TurnRefreshRequest : public StunRequest {
88 public:
89 explicit TurnRefreshRequest(TurnPort* port);
90 virtual void Prepare(StunMessage* request);
91 virtual void OnResponse(StunMessage* response);
92 virtual void OnErrorResponse(StunMessage* response);
93 virtual void OnTimeout();
94
95 private:
96 TurnPort* port_;
97 };
98
99 class TurnCreatePermissionRequest : public StunRequest,
100 public sigslot::has_slots<> {
101 public:
102 TurnCreatePermissionRequest(TurnPort* port, TurnEntry* entry,
103 const talk_base::SocketAddress& ext_addr);
104 virtual void Prepare(StunMessage* request);
105 virtual void OnResponse(StunMessage* response);
106 virtual void OnErrorResponse(StunMessage* response);
107 virtual void OnTimeout();
108
109 private:
110 void OnEntryDestroyed(TurnEntry* entry);
111
112 TurnPort* port_;
113 TurnEntry* entry_;
114 talk_base::SocketAddress ext_addr_;
115 };
116
117 class TurnChannelBindRequest : public StunRequest,
118 public sigslot::has_slots<> {
119 public:
120 TurnChannelBindRequest(TurnPort* port, TurnEntry* entry, int channel_id,
121 const talk_base::SocketAddress& ext_addr);
122 virtual void Prepare(StunMessage* request);
123 virtual void OnResponse(StunMessage* response);
124 virtual void OnErrorResponse(StunMessage* response);
125 virtual void OnTimeout();
126
127 private:
128 void OnEntryDestroyed(TurnEntry* entry);
129
130 TurnPort* port_;
131 TurnEntry* entry_;
132 int channel_id_;
133 talk_base::SocketAddress ext_addr_;
134 };
135
136 // Manages a "connection" to a remote destination. We will attempt to bring up
137 // a channel for this remote destination to reduce the overhead of sending data.
138 class TurnEntry : public sigslot::has_slots<> {
139 public:
140 enum BindState { STATE_UNBOUND, STATE_BINDING, STATE_BOUND };
141 TurnEntry(TurnPort* port, int channel_id,
142 const talk_base::SocketAddress& ext_addr);
143
port()144 TurnPort* port() { return port_; }
145
channel_id() const146 int channel_id() const { return channel_id_; }
address() const147 const talk_base::SocketAddress& address() const { return ext_addr_; }
state() const148 BindState state() const { return state_; }
149
150 // Helper methods to send permission and channel bind requests.
151 void SendCreatePermissionRequest();
152 void SendChannelBindRequest(int delay);
153 // Sends a packet to the given destination address.
154 // This will wrap the packet in STUN if necessary.
155 int Send(const void* data, size_t size, bool payload,
156 talk_base::DiffServCodePoint dscp);
157
158 void OnCreatePermissionSuccess();
159 void OnCreatePermissionError(StunMessage* response, int code);
160 void OnChannelBindSuccess();
161 void OnChannelBindError(StunMessage* response, int code);
162 // Signal sent when TurnEntry is destroyed.
163 sigslot::signal1<TurnEntry*> SignalDestroyed;
164
165 private:
166 TurnPort* port_;
167 int channel_id_;
168 talk_base::SocketAddress ext_addr_;
169 BindState state_;
170 };
171
TurnPort(talk_base::Thread * thread,talk_base::PacketSocketFactory * factory,talk_base::Network * network,const talk_base::IPAddress & ip,int min_port,int max_port,const std::string & username,const std::string & password,const ProtocolAddress & server_address,const RelayCredentials & credentials)172 TurnPort::TurnPort(talk_base::Thread* thread,
173 talk_base::PacketSocketFactory* factory,
174 talk_base::Network* network,
175 const talk_base::IPAddress& ip,
176 int min_port, int max_port,
177 const std::string& username,
178 const std::string& password,
179 const ProtocolAddress& server_address,
180 const RelayCredentials& credentials)
181 : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port,
182 username, password),
183 server_address_(server_address),
184 credentials_(credentials),
185 resolver_(NULL),
186 error_(0),
187 request_manager_(thread),
188 next_channel_number_(TURN_CHANNEL_NUMBER_START),
189 connected_(false) {
190 request_manager_.SignalSendPacket.connect(this, &TurnPort::OnSendStunPacket);
191 }
192
~TurnPort()193 TurnPort::~TurnPort() {
194 // TODO(juberti): Should this even be necessary?
195 while (!entries_.empty()) {
196 DestroyEntry(entries_.front()->address());
197 }
198 }
199
PrepareAddress()200 void TurnPort::PrepareAddress() {
201 if (credentials_.username.empty() ||
202 credentials_.password.empty()) {
203 LOG(LS_ERROR) << "Allocation can't be started without setting the"
204 << " TURN server credentials for the user.";
205 OnAllocateError();
206 return;
207 }
208
209 if (!server_address_.address.port()) {
210 // We will set default TURN port, if no port is set in the address.
211 server_address_.address.SetPort(TURN_DEFAULT_PORT);
212 }
213
214 if (server_address_.address.IsUnresolved()) {
215 ResolveTurnAddress(server_address_.address);
216 } else {
217 // If protocol family of server address doesn't match with local, return.
218 if (!IsCompatibleAddress(server_address_.address)) {
219 LOG(LS_ERROR) << "Server IP address family does not match with "
220 << "local host address family type";
221 OnAllocateError();
222 return;
223 }
224
225 LOG_J(LS_INFO, this) << "Trying to connect to TURN server via "
226 << ProtoToString(server_address_.proto) << " @ "
227 << server_address_.address.ToSensitiveString();
228 if (server_address_.proto == PROTO_UDP) {
229 socket_.reset(socket_factory()->CreateUdpSocket(
230 talk_base::SocketAddress(ip(), 0), min_port(), max_port()));
231 } else if (server_address_.proto == PROTO_TCP) {
232 int opts = talk_base::PacketSocketFactory::OPT_STUN;
233 // If secure bit is enabled in server address, use TLS over TCP.
234 if (server_address_.secure) {
235 opts |= talk_base::PacketSocketFactory::OPT_TLS;
236 }
237
238 socket_.reset(socket_factory()->CreateClientTcpSocket(
239 talk_base::SocketAddress(ip(), 0), server_address_.address,
240 proxy(), user_agent(), opts));
241 }
242
243 if (!socket_) {
244 OnAllocateError();
245 return;
246 }
247
248 // Apply options if any.
249 for (SocketOptionsMap::iterator iter = socket_options_.begin();
250 iter != socket_options_.end(); ++iter) {
251 socket_->SetOption(iter->first, iter->second);
252 }
253
254 socket_->SignalReadPacket.connect(this, &TurnPort::OnReadPacket);
255 socket_->SignalReadyToSend.connect(this, &TurnPort::OnReadyToSend);
256
257 if (server_address_.proto == PROTO_TCP) {
258 socket_->SignalConnect.connect(this, &TurnPort::OnSocketConnect);
259 socket_->SignalClose.connect(this, &TurnPort::OnSocketClose);
260 } else {
261 // If its UDP, send AllocateRequest now.
262 // For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
263 SendRequest(new TurnAllocateRequest(this), 0);
264 }
265 }
266 }
267
OnSocketConnect(talk_base::AsyncPacketSocket * socket)268 void TurnPort::OnSocketConnect(talk_base::AsyncPacketSocket* socket) {
269 LOG(LS_INFO) << "TurnPort connected to " << socket->GetRemoteAddress()
270 << " using tcp.";
271 SendRequest(new TurnAllocateRequest(this), 0);
272 }
273
OnSocketClose(talk_base::AsyncPacketSocket * socket,int error)274 void TurnPort::OnSocketClose(talk_base::AsyncPacketSocket* socket, int error) {
275 LOG_J(LS_WARNING, this) << "Connection with server failed, error=" << error;
276 if (!connected_) {
277 OnAllocateError();
278 }
279 }
280
CreateConnection(const Candidate & address,CandidateOrigin origin)281 Connection* TurnPort::CreateConnection(const Candidate& address,
282 CandidateOrigin origin) {
283 // TURN-UDP can only connect to UDP candidates.
284 if (address.protocol() != UDP_PROTOCOL_NAME) {
285 return NULL;
286 }
287
288 if (!IsCompatibleAddress(address.address())) {
289 return NULL;
290 }
291
292 // Create an entry, if needed, so we can get our permissions set up correctly.
293 CreateEntry(address.address());
294
295 // TODO(juberti): The '0' index will need to change if we start gathering STUN
296 // candidates on this port.
297 ProxyConnection* conn = new ProxyConnection(this, 0, address);
298 conn->SignalDestroyed.connect(this, &TurnPort::OnConnectionDestroyed);
299 AddConnection(conn);
300 return conn;
301 }
302
SetOption(talk_base::Socket::Option opt,int value)303 int TurnPort::SetOption(talk_base::Socket::Option opt, int value) {
304 // DSCP option is not passed to the socket.
305 // TODO(mallinath) - After we have the support on socket,
306 // remove this specialization.
307 if (opt == talk_base::Socket::OPT_DSCP) {
308 SetDefaultDscpValue(static_cast<talk_base::DiffServCodePoint>(value));
309 return 0;
310 }
311
312 if (!socket_) {
313 // If socket is not created yet, these options will be applied during socket
314 // creation.
315 socket_options_[opt] = value;
316 return 0;
317 }
318 return socket_->SetOption(opt, value);
319 }
320
GetOption(talk_base::Socket::Option opt,int * value)321 int TurnPort::GetOption(talk_base::Socket::Option opt, int* value) {
322 if (!socket_)
323 return -1;
324
325 return socket_->GetOption(opt, value);
326 }
327
GetError()328 int TurnPort::GetError() {
329 return error_;
330 }
331
SendTo(const void * data,size_t size,const talk_base::SocketAddress & addr,talk_base::DiffServCodePoint dscp,bool payload)332 int TurnPort::SendTo(const void* data, size_t size,
333 const talk_base::SocketAddress& addr,
334 talk_base::DiffServCodePoint dscp,
335 bool payload) {
336 // Try to find an entry for this specific address; we should have one.
337 TurnEntry* entry = FindEntry(addr);
338 ASSERT(entry != NULL);
339 if (!entry) {
340 return 0;
341 }
342
343 if (!connected()) {
344 error_ = EWOULDBLOCK;
345 return SOCKET_ERROR;
346 }
347
348 // Send the actual contents to the server using the usual mechanism.
349 int sent = entry->Send(data, size, payload, dscp);
350 if (sent <= 0) {
351 return SOCKET_ERROR;
352 }
353
354 // The caller of the function is expecting the number of user data bytes,
355 // rather than the size of the packet.
356 return static_cast<int>(size);
357 }
358
OnReadPacket(talk_base::AsyncPacketSocket * socket,const char * data,size_t size,const talk_base::SocketAddress & remote_addr,const talk_base::PacketTime & packet_time)359 void TurnPort::OnReadPacket(
360 talk_base::AsyncPacketSocket* socket, const char* data, size_t size,
361 const talk_base::SocketAddress& remote_addr,
362 const talk_base::PacketTime& packet_time) {
363 ASSERT(socket == socket_.get());
364 ASSERT(remote_addr == server_address_.address);
365
366 // The message must be at least the size of a channel header.
367 if (size < TURN_CHANNEL_HEADER_SIZE) {
368 LOG_J(LS_WARNING, this) << "Received TURN message that was too short";
369 return;
370 }
371
372 // Check the message type, to see if is a Channel Data message.
373 // The message will either be channel data, a TURN data indication, or
374 // a response to a previous request.
375 uint16 msg_type = talk_base::GetBE16(data);
376 if (IsTurnChannelData(msg_type)) {
377 HandleChannelData(msg_type, data, size, packet_time);
378 } else if (msg_type == TURN_DATA_INDICATION) {
379 HandleDataIndication(data, size, packet_time);
380 } else {
381 // This must be a response for one of our requests.
382 // Check success responses, but not errors, for MESSAGE-INTEGRITY.
383 if (IsStunSuccessResponseType(msg_type) &&
384 !StunMessage::ValidateMessageIntegrity(data, size, hash())) {
385 LOG_J(LS_WARNING, this) << "Received TURN message with invalid "
386 << "message integrity, msg_type=" << msg_type;
387 return;
388 }
389 request_manager_.CheckResponse(data, size);
390 }
391 }
392
OnReadyToSend(talk_base::AsyncPacketSocket * socket)393 void TurnPort::OnReadyToSend(talk_base::AsyncPacketSocket* socket) {
394 if (connected_) {
395 Port::OnReadyToSend();
396 }
397 }
398
ResolveTurnAddress(const talk_base::SocketAddress & address)399 void TurnPort::ResolveTurnAddress(const talk_base::SocketAddress& address) {
400 if (resolver_)
401 return;
402
403 resolver_ = socket_factory()->CreateAsyncResolver();
404 resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
405 resolver_->Start(address);
406 }
407
OnResolveResult(talk_base::AsyncResolverInterface * resolver)408 void TurnPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
409 ASSERT(resolver == resolver_);
410 if (resolver_->GetError() != 0 ||
411 !resolver_->GetResolvedAddress(ip().family(), &server_address_.address)) {
412 LOG_J(LS_WARNING, this) << "TURN host lookup received error "
413 << resolver_->GetError();
414 OnAllocateError();
415 return;
416 }
417
418 PrepareAddress();
419 }
420
OnSendStunPacket(const void * data,size_t size,StunRequest * request)421 void TurnPort::OnSendStunPacket(const void* data, size_t size,
422 StunRequest* request) {
423 if (Send(data, size, DefaultDscpValue()) < 0) {
424 LOG_J(LS_ERROR, this) << "Failed to send TURN message, err="
425 << socket_->GetError();
426 }
427 }
428
OnStunAddress(const talk_base::SocketAddress & address)429 void TurnPort::OnStunAddress(const talk_base::SocketAddress& address) {
430 // For relay, mapped address is rel-addr.
431 set_related_address(address);
432 }
433
OnAllocateSuccess(const talk_base::SocketAddress & address)434 void TurnPort::OnAllocateSuccess(const talk_base::SocketAddress& address) {
435 connected_ = true;
436 AddAddress(address,
437 socket_->GetLocalAddress(),
438 "udp",
439 RELAY_PORT_TYPE,
440 GetRelayPreference(server_address_.proto, server_address_.secure),
441 true);
442 }
443
OnAllocateError()444 void TurnPort::OnAllocateError() {
445 // We will send SignalPortError asynchronously as this can be sent during
446 // port initialization. This way it will not be blocking other port
447 // creation.
448 thread()->Post(this, MSG_ERROR);
449 }
450
OnMessage(talk_base::Message * message)451 void TurnPort::OnMessage(talk_base::Message* message) {
452 if (message->message_id == MSG_ERROR) {
453 SignalPortError(this);
454 return;
455 }
456
457 Port::OnMessage(message);
458 }
459
OnAllocateRequestTimeout()460 void TurnPort::OnAllocateRequestTimeout() {
461 OnAllocateError();
462 }
463
HandleDataIndication(const char * data,size_t size,const talk_base::PacketTime & packet_time)464 void TurnPort::HandleDataIndication(const char* data, size_t size,
465 const talk_base::PacketTime& packet_time) {
466 // Read in the message, and process according to RFC5766, Section 10.4.
467 talk_base::ByteBuffer buf(data, size);
468 TurnMessage msg;
469 if (!msg.Read(&buf)) {
470 LOG_J(LS_WARNING, this) << "Received invalid TURN data indication";
471 return;
472 }
473
474 // Check mandatory attributes.
475 const StunAddressAttribute* addr_attr =
476 msg.GetAddress(STUN_ATTR_XOR_PEER_ADDRESS);
477 if (!addr_attr) {
478 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_XOR_PEER_ADDRESS attribute "
479 << "in data indication.";
480 return;
481 }
482
483 const StunByteStringAttribute* data_attr =
484 msg.GetByteString(STUN_ATTR_DATA);
485 if (!data_attr) {
486 LOG_J(LS_WARNING, this) << "Missing STUN_ATTR_DATA attribute in "
487 << "data indication.";
488 return;
489 }
490
491 // Verify that the data came from somewhere we think we have a permission for.
492 talk_base::SocketAddress ext_addr(addr_attr->GetAddress());
493 if (!HasPermission(ext_addr.ipaddr())) {
494 LOG_J(LS_WARNING, this) << "Received TURN data indication with invalid "
495 << "peer address, addr="
496 << ext_addr.ToSensitiveString();
497 return;
498 }
499
500 DispatchPacket(data_attr->bytes(), data_attr->length(), ext_addr,
501 PROTO_UDP, packet_time);
502 }
503
HandleChannelData(int channel_id,const char * data,size_t size,const talk_base::PacketTime & packet_time)504 void TurnPort::HandleChannelData(int channel_id, const char* data,
505 size_t size,
506 const talk_base::PacketTime& packet_time) {
507 // Read the message, and process according to RFC5766, Section 11.6.
508 // 0 1 2 3
509 // 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
510 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511 // | Channel Number | Length |
512 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513 // | |
514 // / Application Data /
515 // / /
516 // | |
517 // | +-------------------------------+
518 // | |
519 // +-------------------------------+
520
521 // Extract header fields from the message.
522 uint16 len = talk_base::GetBE16(data + 2);
523 if (len > size - TURN_CHANNEL_HEADER_SIZE) {
524 LOG_J(LS_WARNING, this) << "Received TURN channel data message with "
525 << "incorrect length, len=" << len;
526 return;
527 }
528 // Allowing messages larger than |len|, as ChannelData can be padded.
529
530 TurnEntry* entry = FindEntry(channel_id);
531 if (!entry) {
532 LOG_J(LS_WARNING, this) << "Received TURN channel data message for invalid "
533 << "channel, channel_id=" << channel_id;
534 return;
535 }
536
537 DispatchPacket(data + TURN_CHANNEL_HEADER_SIZE, len, entry->address(),
538 PROTO_UDP, packet_time);
539 }
540
DispatchPacket(const char * data,size_t size,const talk_base::SocketAddress & remote_addr,ProtocolType proto,const talk_base::PacketTime & packet_time)541 void TurnPort::DispatchPacket(const char* data, size_t size,
542 const talk_base::SocketAddress& remote_addr,
543 ProtocolType proto, const talk_base::PacketTime& packet_time) {
544 if (Connection* conn = GetConnection(remote_addr)) {
545 conn->OnReadPacket(data, size, packet_time);
546 } else {
547 Port::OnReadPacket(data, size, remote_addr, proto);
548 }
549 }
550
ScheduleRefresh(int lifetime)551 bool TurnPort::ScheduleRefresh(int lifetime) {
552 // Lifetime is in seconds; we schedule a refresh for one minute less.
553 if (lifetime < 2 * 60) {
554 LOG_J(LS_WARNING, this) << "Received response with lifetime that was "
555 << "too short, lifetime=" << lifetime;
556 return false;
557 }
558
559 SendRequest(new TurnRefreshRequest(this), (lifetime - 60) * 1000);
560 return true;
561 }
562
SendRequest(StunRequest * req,int delay)563 void TurnPort::SendRequest(StunRequest* req, int delay) {
564 request_manager_.SendDelayed(req, delay);
565 }
566
AddRequestAuthInfo(StunMessage * msg)567 void TurnPort::AddRequestAuthInfo(StunMessage* msg) {
568 // If we've gotten the necessary data from the server, add it to our request.
569 VERIFY(!hash_.empty());
570 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
571 STUN_ATTR_USERNAME, credentials_.username)));
572 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
573 STUN_ATTR_REALM, realm_)));
574 VERIFY(msg->AddAttribute(new StunByteStringAttribute(
575 STUN_ATTR_NONCE, nonce_)));
576 VERIFY(msg->AddMessageIntegrity(hash()));
577 }
578
Send(const void * data,size_t len,talk_base::DiffServCodePoint dscp)579 int TurnPort::Send(const void* data, size_t len,
580 talk_base::DiffServCodePoint dscp) {
581 return socket_->SendTo(data, len, server_address_.address, dscp);
582 }
583
UpdateHash()584 void TurnPort::UpdateHash() {
585 VERIFY(ComputeStunCredentialHash(credentials_.username, realm_,
586 credentials_.password, &hash_));
587 }
588
UpdateNonce(StunMessage * response)589 bool TurnPort::UpdateNonce(StunMessage* response) {
590 // When stale nonce error received, we should update
591 // hash and store realm and nonce.
592 // Check the mandatory attributes.
593 const StunByteStringAttribute* realm_attr =
594 response->GetByteString(STUN_ATTR_REALM);
595 if (!realm_attr) {
596 LOG(LS_ERROR) << "Missing STUN_ATTR_REALM attribute in "
597 << "stale nonce error response.";
598 return false;
599 }
600 set_realm(realm_attr->GetString());
601
602 const StunByteStringAttribute* nonce_attr =
603 response->GetByteString(STUN_ATTR_NONCE);
604 if (!nonce_attr) {
605 LOG(LS_ERROR) << "Missing STUN_ATTR_NONCE attribute in "
606 << "stale nonce error response.";
607 return false;
608 }
609 set_nonce(nonce_attr->GetString());
610 return true;
611 }
612
MatchesIP(TurnEntry * e,talk_base::IPAddress ipaddr)613 static bool MatchesIP(TurnEntry* e, talk_base::IPAddress ipaddr) {
614 return e->address().ipaddr() == ipaddr;
615 }
HasPermission(const talk_base::IPAddress & ipaddr) const616 bool TurnPort::HasPermission(const talk_base::IPAddress& ipaddr) const {
617 return (std::find_if(entries_.begin(), entries_.end(),
618 std::bind2nd(std::ptr_fun(MatchesIP), ipaddr)) != entries_.end());
619 }
620
MatchesAddress(TurnEntry * e,talk_base::SocketAddress addr)621 static bool MatchesAddress(TurnEntry* e, talk_base::SocketAddress addr) {
622 return e->address() == addr;
623 }
FindEntry(const talk_base::SocketAddress & addr) const624 TurnEntry* TurnPort::FindEntry(const talk_base::SocketAddress& addr) const {
625 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
626 std::bind2nd(std::ptr_fun(MatchesAddress), addr));
627 return (it != entries_.end()) ? *it : NULL;
628 }
629
MatchesChannelId(TurnEntry * e,int id)630 static bool MatchesChannelId(TurnEntry* e, int id) {
631 return e->channel_id() == id;
632 }
FindEntry(int channel_id) const633 TurnEntry* TurnPort::FindEntry(int channel_id) const {
634 EntryList::const_iterator it = std::find_if(entries_.begin(), entries_.end(),
635 std::bind2nd(std::ptr_fun(MatchesChannelId), channel_id));
636 return (it != entries_.end()) ? *it : NULL;
637 }
638
CreateEntry(const talk_base::SocketAddress & addr)639 TurnEntry* TurnPort::CreateEntry(const talk_base::SocketAddress& addr) {
640 ASSERT(FindEntry(addr) == NULL);
641 TurnEntry* entry = new TurnEntry(this, next_channel_number_++, addr);
642 entries_.push_back(entry);
643 return entry;
644 }
645
DestroyEntry(const talk_base::SocketAddress & addr)646 void TurnPort::DestroyEntry(const talk_base::SocketAddress& addr) {
647 TurnEntry* entry = FindEntry(addr);
648 ASSERT(entry != NULL);
649 entry->SignalDestroyed(entry);
650 entries_.remove(entry);
651 delete entry;
652 }
653
OnConnectionDestroyed(Connection * conn)654 void TurnPort::OnConnectionDestroyed(Connection* conn) {
655 // Destroying TurnEntry for the connection, which is already destroyed.
656 DestroyEntry(conn->remote_candidate().address());
657 }
658
TurnAllocateRequest(TurnPort * port)659 TurnAllocateRequest::TurnAllocateRequest(TurnPort* port)
660 : StunRequest(new TurnMessage()),
661 port_(port) {
662 }
663
Prepare(StunMessage * request)664 void TurnAllocateRequest::Prepare(StunMessage* request) {
665 // Create the request as indicated in RFC 5766, Section 6.1.
666 request->SetType(TURN_ALLOCATE_REQUEST);
667 StunUInt32Attribute* transport_attr = StunAttribute::CreateUInt32(
668 STUN_ATTR_REQUESTED_TRANSPORT);
669 transport_attr->SetValue(IPPROTO_UDP << 24);
670 VERIFY(request->AddAttribute(transport_attr));
671 if (!port_->hash().empty()) {
672 port_->AddRequestAuthInfo(request);
673 }
674 }
675
OnResponse(StunMessage * response)676 void TurnAllocateRequest::OnResponse(StunMessage* response) {
677 // Check mandatory attributes as indicated in RFC5766, Section 6.3.
678 const StunAddressAttribute* mapped_attr =
679 response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
680 if (!mapped_attr) {
681 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
682 << "attribute in allocate success response";
683 return;
684 }
685
686 // TODO(mallinath) - Use mapped address for STUN candidate.
687 port_->OnStunAddress(mapped_attr->GetAddress());
688
689 const StunAddressAttribute* relayed_attr =
690 response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
691 if (!relayed_attr) {
692 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
693 << "attribute in allocate success response";
694 return;
695 }
696
697 const StunUInt32Attribute* lifetime_attr =
698 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
699 if (!lifetime_attr) {
700 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
701 << "allocate success response";
702 return;
703 }
704 // Notify the port the allocate succeeded, and schedule a refresh request.
705 port_->OnAllocateSuccess(relayed_attr->GetAddress());
706 port_->ScheduleRefresh(lifetime_attr->value());
707 }
708
OnErrorResponse(StunMessage * response)709 void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
710 // Process error response according to RFC5766, Section 6.4.
711 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
712 switch (error_code->code()) {
713 case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
714 OnAuthChallenge(response, error_code->code());
715 break;
716 default:
717 LOG_J(LS_WARNING, port_) << "Allocate response error, code="
718 << error_code->code();
719 port_->OnAllocateError();
720 }
721 }
722
OnTimeout()723 void TurnAllocateRequest::OnTimeout() {
724 LOG_J(LS_WARNING, port_) << "Allocate request timeout";
725 port_->OnAllocateRequestTimeout();
726 }
727
OnAuthChallenge(StunMessage * response,int code)728 void TurnAllocateRequest::OnAuthChallenge(StunMessage* response, int code) {
729 // If we failed to authenticate even after we sent our credentials, fail hard.
730 if (code == STUN_ERROR_UNAUTHORIZED && !port_->hash().empty()) {
731 LOG_J(LS_WARNING, port_) << "Failed to authenticate with the server "
732 << "after challenge.";
733 port_->OnAllocateError();
734 return;
735 }
736
737 // Check the mandatory attributes.
738 const StunByteStringAttribute* realm_attr =
739 response->GetByteString(STUN_ATTR_REALM);
740 if (!realm_attr) {
741 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_REALM attribute in "
742 << "allocate unauthorized response.";
743 return;
744 }
745 port_->set_realm(realm_attr->GetString());
746
747 const StunByteStringAttribute* nonce_attr =
748 response->GetByteString(STUN_ATTR_NONCE);
749 if (!nonce_attr) {
750 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_NONCE attribute in "
751 << "allocate unauthorized response.";
752 return;
753 }
754 port_->set_nonce(nonce_attr->GetString());
755
756 // Send another allocate request, with the received realm and nonce values.
757 port_->SendRequest(new TurnAllocateRequest(port_), 0);
758 }
759
TurnRefreshRequest(TurnPort * port)760 TurnRefreshRequest::TurnRefreshRequest(TurnPort* port)
761 : StunRequest(new TurnMessage()),
762 port_(port) {
763 }
764
Prepare(StunMessage * request)765 void TurnRefreshRequest::Prepare(StunMessage* request) {
766 // Create the request as indicated in RFC 5766, Section 7.1.
767 // No attributes need to be included.
768 request->SetType(TURN_REFRESH_REQUEST);
769 port_->AddRequestAuthInfo(request);
770 }
771
OnResponse(StunMessage * response)772 void TurnRefreshRequest::OnResponse(StunMessage* response) {
773 // Check mandatory attributes as indicated in RFC5766, Section 7.3.
774 const StunUInt32Attribute* lifetime_attr =
775 response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
776 if (!lifetime_attr) {
777 LOG_J(LS_WARNING, port_) << "Missing STUN_ATTR_TURN_LIFETIME attribute in "
778 << "refresh success response.";
779 return;
780 }
781
782 // Schedule a refresh based on the returned lifetime value.
783 port_->ScheduleRefresh(lifetime_attr->value());
784 }
785
OnErrorResponse(StunMessage * response)786 void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
787 // TODO(juberti): Handle 437 error response as a success.
788 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
789 LOG_J(LS_WARNING, port_) << "Refresh response error, code="
790 << error_code->code();
791
792 if (error_code->code() == STUN_ERROR_STALE_NONCE) {
793 if (port_->UpdateNonce(response)) {
794 // Send RefreshRequest immediately.
795 port_->SendRequest(new TurnRefreshRequest(port_), 0);
796 }
797 }
798 }
799
OnTimeout()800 void TurnRefreshRequest::OnTimeout() {
801 }
802
TurnCreatePermissionRequest(TurnPort * port,TurnEntry * entry,const talk_base::SocketAddress & ext_addr)803 TurnCreatePermissionRequest::TurnCreatePermissionRequest(
804 TurnPort* port, TurnEntry* entry,
805 const talk_base::SocketAddress& ext_addr)
806 : StunRequest(new TurnMessage()),
807 port_(port),
808 entry_(entry),
809 ext_addr_(ext_addr) {
810 entry_->SignalDestroyed.connect(
811 this, &TurnCreatePermissionRequest::OnEntryDestroyed);
812 }
813
Prepare(StunMessage * request)814 void TurnCreatePermissionRequest::Prepare(StunMessage* request) {
815 // Create the request as indicated in RFC5766, Section 9.1.
816 request->SetType(TURN_CREATE_PERMISSION_REQUEST);
817 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
818 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
819 port_->AddRequestAuthInfo(request);
820 }
821
OnResponse(StunMessage * response)822 void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
823 if (entry_) {
824 entry_->OnCreatePermissionSuccess();
825 }
826 }
827
OnErrorResponse(StunMessage * response)828 void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
829 if (entry_) {
830 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
831 entry_->OnCreatePermissionError(response, error_code->code());
832 }
833 }
834
OnTimeout()835 void TurnCreatePermissionRequest::OnTimeout() {
836 LOG_J(LS_WARNING, port_) << "Create permission timeout";
837 }
838
OnEntryDestroyed(TurnEntry * entry)839 void TurnCreatePermissionRequest::OnEntryDestroyed(TurnEntry* entry) {
840 ASSERT(entry_ == entry);
841 entry_ = NULL;
842 }
843
TurnChannelBindRequest(TurnPort * port,TurnEntry * entry,int channel_id,const talk_base::SocketAddress & ext_addr)844 TurnChannelBindRequest::TurnChannelBindRequest(
845 TurnPort* port, TurnEntry* entry,
846 int channel_id, const talk_base::SocketAddress& ext_addr)
847 : StunRequest(new TurnMessage()),
848 port_(port),
849 entry_(entry),
850 channel_id_(channel_id),
851 ext_addr_(ext_addr) {
852 entry_->SignalDestroyed.connect(
853 this, &TurnChannelBindRequest::OnEntryDestroyed);
854 }
855
Prepare(StunMessage * request)856 void TurnChannelBindRequest::Prepare(StunMessage* request) {
857 // Create the request as indicated in RFC5766, Section 11.1.
858 request->SetType(TURN_CHANNEL_BIND_REQUEST);
859 VERIFY(request->AddAttribute(new StunUInt32Attribute(
860 STUN_ATTR_CHANNEL_NUMBER, channel_id_ << 16)));
861 VERIFY(request->AddAttribute(new StunXorAddressAttribute(
862 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
863 port_->AddRequestAuthInfo(request);
864 }
865
OnResponse(StunMessage * response)866 void TurnChannelBindRequest::OnResponse(StunMessage* response) {
867 if (entry_) {
868 entry_->OnChannelBindSuccess();
869 // Refresh the channel binding just under the permission timeout
870 // threshold. The channel binding has a longer lifetime, but
871 // this is the easiest way to keep both the channel and the
872 // permission from expiring.
873 entry_->SendChannelBindRequest(TURN_PERMISSION_TIMEOUT - 60 * 1000);
874 }
875 }
876
OnErrorResponse(StunMessage * response)877 void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
878 if (entry_) {
879 const StunErrorCodeAttribute* error_code = response->GetErrorCode();
880 entry_->OnChannelBindError(response, error_code->code());
881 }
882 }
883
OnTimeout()884 void TurnChannelBindRequest::OnTimeout() {
885 LOG_J(LS_WARNING, port_) << "Channel bind timeout";
886 }
887
OnEntryDestroyed(TurnEntry * entry)888 void TurnChannelBindRequest::OnEntryDestroyed(TurnEntry* entry) {
889 ASSERT(entry_ == entry);
890 entry_ = NULL;
891 }
892
TurnEntry(TurnPort * port,int channel_id,const talk_base::SocketAddress & ext_addr)893 TurnEntry::TurnEntry(TurnPort* port, int channel_id,
894 const talk_base::SocketAddress& ext_addr)
895 : port_(port),
896 channel_id_(channel_id),
897 ext_addr_(ext_addr),
898 state_(STATE_UNBOUND) {
899 // Creating permission for |ext_addr_|.
900 SendCreatePermissionRequest();
901 }
902
SendCreatePermissionRequest()903 void TurnEntry::SendCreatePermissionRequest() {
904 port_->SendRequest(new TurnCreatePermissionRequest(
905 port_, this, ext_addr_), 0);
906 }
907
SendChannelBindRequest(int delay)908 void TurnEntry::SendChannelBindRequest(int delay) {
909 port_->SendRequest(new TurnChannelBindRequest(
910 port_, this, channel_id_, ext_addr_), delay);
911 }
912
Send(const void * data,size_t size,bool payload,talk_base::DiffServCodePoint dscp)913 int TurnEntry::Send(const void* data, size_t size, bool payload,
914 talk_base::DiffServCodePoint dscp) {
915 talk_base::ByteBuffer buf;
916 if (state_ != STATE_BOUND) {
917 // If we haven't bound the channel yet, we have to use a Send Indication.
918 TurnMessage msg;
919 msg.SetType(TURN_SEND_INDICATION);
920 msg.SetTransactionID(
921 talk_base::CreateRandomString(kStunTransactionIdLength));
922 VERIFY(msg.AddAttribute(new StunXorAddressAttribute(
923 STUN_ATTR_XOR_PEER_ADDRESS, ext_addr_)));
924 VERIFY(msg.AddAttribute(new StunByteStringAttribute(
925 STUN_ATTR_DATA, data, size)));
926 VERIFY(msg.Write(&buf));
927
928 // If we're sending real data, request a channel bind that we can use later.
929 if (state_ == STATE_UNBOUND && payload) {
930 SendChannelBindRequest(0);
931 state_ = STATE_BINDING;
932 }
933 } else {
934 // If the channel is bound, we can send the data as a Channel Message.
935 buf.WriteUInt16(channel_id_);
936 buf.WriteUInt16(static_cast<uint16>(size));
937 buf.WriteBytes(reinterpret_cast<const char*>(data), size);
938 }
939 return port_->Send(buf.Data(), buf.Length(), dscp);
940 }
941
OnCreatePermissionSuccess()942 void TurnEntry::OnCreatePermissionSuccess() {
943 LOG_J(LS_INFO, port_) << "Create permission for "
944 << ext_addr_.ToSensitiveString()
945 << " succeeded";
946 // For success result code will be 0.
947 port_->SignalCreatePermissionResult(port_, ext_addr_, 0);
948 }
949
OnCreatePermissionError(StunMessage * response,int code)950 void TurnEntry::OnCreatePermissionError(StunMessage* response, int code) {
951 LOG_J(LS_WARNING, port_) << "Create permission for "
952 << ext_addr_.ToSensitiveString()
953 << " failed, code=" << code;
954 if (code == STUN_ERROR_STALE_NONCE) {
955 if (port_->UpdateNonce(response)) {
956 SendCreatePermissionRequest();
957 }
958 } else {
959 // Send signal with error code.
960 port_->SignalCreatePermissionResult(port_, ext_addr_, code);
961 }
962 }
963
OnChannelBindSuccess()964 void TurnEntry::OnChannelBindSuccess() {
965 LOG_J(LS_INFO, port_) << "Channel bind for " << ext_addr_.ToSensitiveString()
966 << " succeeded";
967 ASSERT(state_ == STATE_BINDING || state_ == STATE_BOUND);
968 state_ = STATE_BOUND;
969 }
970
OnChannelBindError(StunMessage * response,int code)971 void TurnEntry::OnChannelBindError(StunMessage* response, int code) {
972 // TODO(mallinath) - Implement handling of error response for channel
973 // bind request as per http://tools.ietf.org/html/rfc5766#section-11.3
974 LOG_J(LS_WARNING, port_) << "Channel bind for "
975 << ext_addr_.ToSensitiveString()
976 << " failed, code=" << code;
977 if (code == STUN_ERROR_STALE_NONCE) {
978 if (port_->UpdateNonce(response)) {
979 // Send channel bind request with fresh nonce.
980 SendChannelBindRequest(0);
981 }
982 }
983 }
984
985 } // namespace cricket
986