• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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