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