1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/p2p/base/relayserver.h"
12 
13 #ifdef WEBRTC_POSIX
14 #include <errno.h>
15 #endif  // WEBRTC_POSIX
16 
17 #include <algorithm>
18 
19 #include "webrtc/base/asynctcpsocket.h"
20 #include "webrtc/base/checks.h"
21 #include "webrtc/base/helpers.h"
22 #include "webrtc/base/logging.h"
23 #include "webrtc/base/socketadapters.h"
24 
25 namespace cricket {
26 
27 // By default, we require a ping every 90 seconds.
28 const int MAX_LIFETIME = 15 * 60 * 1000;
29 
30 // The number of bytes in each of the usernames we use.
31 const uint32_t USERNAME_LENGTH = 16;
32 
33 // Calls SendTo on the given socket and logs any bad results.
Send(rtc::AsyncPacketSocket * socket,const char * bytes,size_t size,const rtc::SocketAddress & addr)34 void Send(rtc::AsyncPacketSocket* socket, const char* bytes, size_t size,
35           const rtc::SocketAddress& addr) {
36   rtc::PacketOptions options;
37   int result = socket->SendTo(bytes, size, addr, options);
38   if (result < static_cast<int>(size)) {
39     LOG(LS_ERROR) << "SendTo wrote only " << result << " of " << size
40                   << " bytes";
41   } else if (result < 0) {
42     LOG_ERR(LS_ERROR) << "SendTo";
43   }
44 }
45 
46 // Sends the given STUN message on the given socket.
SendStun(const StunMessage & msg,rtc::AsyncPacketSocket * socket,const rtc::SocketAddress & addr)47 void SendStun(const StunMessage& msg,
48               rtc::AsyncPacketSocket* socket,
49               const rtc::SocketAddress& addr) {
50   rtc::ByteBufferWriter buf;
51   msg.Write(&buf);
52   Send(socket, buf.Data(), buf.Length(), addr);
53 }
54 
55 // Constructs a STUN error response and sends it on the given socket.
SendStunError(const StunMessage & msg,rtc::AsyncPacketSocket * socket,const rtc::SocketAddress & remote_addr,int error_code,const char * error_desc,const std::string & magic_cookie)56 void SendStunError(const StunMessage& msg, rtc::AsyncPacketSocket* socket,
57                    const rtc::SocketAddress& remote_addr, int error_code,
58                    const char* error_desc, const std::string& magic_cookie) {
59   RelayMessage err_msg;
60   err_msg.SetType(GetStunErrorResponseType(msg.type()));
61   err_msg.SetTransactionID(msg.transaction_id());
62 
63   StunByteStringAttribute* magic_cookie_attr =
64       StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
65   if (magic_cookie.size() == 0) {
66     magic_cookie_attr->CopyBytes(cricket::TURN_MAGIC_COOKIE_VALUE,
67                                  sizeof(cricket::TURN_MAGIC_COOKIE_VALUE));
68   } else {
69     magic_cookie_attr->CopyBytes(magic_cookie.c_str(), magic_cookie.size());
70   }
71   err_msg.AddAttribute(magic_cookie_attr);
72 
73   StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode();
74   err_code->SetClass(error_code / 100);
75   err_code->SetNumber(error_code % 100);
76   err_code->SetReason(error_desc);
77   err_msg.AddAttribute(err_code);
78 
79   SendStun(err_msg, socket, remote_addr);
80 }
81 
RelayServer(rtc::Thread * thread)82 RelayServer::RelayServer(rtc::Thread* thread)
83   : thread_(thread), log_bindings_(true) {
84 }
85 
~RelayServer()86 RelayServer::~RelayServer() {
87   // Deleting the binding will cause it to be removed from the map.
88   while (!bindings_.empty())
89     delete bindings_.begin()->second;
90   for (size_t i = 0; i < internal_sockets_.size(); ++i)
91     delete internal_sockets_[i];
92   for (size_t i = 0; i < external_sockets_.size(); ++i)
93     delete external_sockets_[i];
94   for (size_t i = 0; i < removed_sockets_.size(); ++i)
95     delete removed_sockets_[i];
96   while (!server_sockets_.empty()) {
97     rtc::AsyncSocket* socket = server_sockets_.begin()->first;
98     server_sockets_.erase(server_sockets_.begin()->first);
99     delete socket;
100   }
101 }
102 
AddInternalSocket(rtc::AsyncPacketSocket * socket)103 void RelayServer::AddInternalSocket(rtc::AsyncPacketSocket* socket) {
104   RTC_DCHECK(internal_sockets_.end() == std::find(internal_sockets_.begin(),
105                                                   internal_sockets_.end(),
106                                                   socket));
107   internal_sockets_.push_back(socket);
108   socket->SignalReadPacket.connect(this, &RelayServer::OnInternalPacket);
109 }
110 
RemoveInternalSocket(rtc::AsyncPacketSocket * socket)111 void RelayServer::RemoveInternalSocket(rtc::AsyncPacketSocket* socket) {
112   SocketList::iterator iter =
113       std::find(internal_sockets_.begin(), internal_sockets_.end(), socket);
114   RTC_DCHECK(iter != internal_sockets_.end());
115   internal_sockets_.erase(iter);
116   removed_sockets_.push_back(socket);
117   socket->SignalReadPacket.disconnect(this);
118 }
119 
AddExternalSocket(rtc::AsyncPacketSocket * socket)120 void RelayServer::AddExternalSocket(rtc::AsyncPacketSocket* socket) {
121   RTC_DCHECK(external_sockets_.end() == std::find(external_sockets_.begin(),
122                                                   external_sockets_.end(),
123                                                   socket));
124   external_sockets_.push_back(socket);
125   socket->SignalReadPacket.connect(this, &RelayServer::OnExternalPacket);
126 }
127 
RemoveExternalSocket(rtc::AsyncPacketSocket * socket)128 void RelayServer::RemoveExternalSocket(rtc::AsyncPacketSocket* socket) {
129   SocketList::iterator iter =
130       std::find(external_sockets_.begin(), external_sockets_.end(), socket);
131   RTC_DCHECK(iter != external_sockets_.end());
132   external_sockets_.erase(iter);
133   removed_sockets_.push_back(socket);
134   socket->SignalReadPacket.disconnect(this);
135 }
136 
AddInternalServerSocket(rtc::AsyncSocket * socket,cricket::ProtocolType proto)137 void RelayServer::AddInternalServerSocket(rtc::AsyncSocket* socket,
138                                           cricket::ProtocolType proto) {
139   RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
140   server_sockets_[socket] = proto;
141   socket->SignalReadEvent.connect(this, &RelayServer::OnReadEvent);
142 }
143 
RemoveInternalServerSocket(rtc::AsyncSocket * socket)144 void RelayServer::RemoveInternalServerSocket(
145     rtc::AsyncSocket* socket) {
146   ServerSocketMap::iterator iter = server_sockets_.find(socket);
147   RTC_DCHECK(iter != server_sockets_.end());
148   server_sockets_.erase(iter);
149   socket->SignalReadEvent.disconnect(this);
150 }
151 
GetConnectionCount() const152 int RelayServer::GetConnectionCount() const {
153   return static_cast<int>(connections_.size());
154 }
155 
GetConnection(int connection) const156 rtc::SocketAddressPair RelayServer::GetConnection(int connection) const {
157   int i = 0;
158   for (ConnectionMap::const_iterator it = connections_.begin();
159        it != connections_.end(); ++it) {
160     if (i == connection) {
161       return it->second->addr_pair();
162     }
163     ++i;
164   }
165   return rtc::SocketAddressPair();
166 }
167 
HasConnection(const rtc::SocketAddress & address) const168 bool RelayServer::HasConnection(const rtc::SocketAddress& address) const {
169   for (ConnectionMap::const_iterator it = connections_.begin();
170        it != connections_.end(); ++it) {
171     if (it->second->addr_pair().destination() == address) {
172       return true;
173     }
174   }
175   return false;
176 }
177 
OnReadEvent(rtc::AsyncSocket * socket)178 void RelayServer::OnReadEvent(rtc::AsyncSocket* socket) {
179   RTC_DCHECK(server_sockets_.find(socket) != server_sockets_.end());
180   AcceptConnection(socket);
181 }
182 
OnInternalPacket(rtc::AsyncPacketSocket * socket,const char * bytes,size_t size,const rtc::SocketAddress & remote_addr,const rtc::PacketTime & packet_time)183 void RelayServer::OnInternalPacket(
184     rtc::AsyncPacketSocket* socket, const char* bytes, size_t size,
185     const rtc::SocketAddress& remote_addr,
186     const rtc::PacketTime& packet_time) {
187 
188   // Get the address of the connection we just received on.
189   rtc::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
190   RTC_DCHECK(!ap.destination().IsNil());
191 
192   // If this did not come from an existing connection, it should be a STUN
193   // allocate request.
194   ConnectionMap::iterator piter = connections_.find(ap);
195   if (piter == connections_.end()) {
196     HandleStunAllocate(bytes, size, ap, socket);
197     return;
198   }
199 
200   RelayServerConnection* int_conn = piter->second;
201 
202   // Handle STUN requests to the server itself.
203   if (int_conn->binding()->HasMagicCookie(bytes, size)) {
204     HandleStun(int_conn, bytes, size);
205     return;
206   }
207 
208   // Otherwise, this is a non-wrapped packet that we are to forward.  Make sure
209   // that this connection has been locked.  (Otherwise, we would not know what
210   // address to forward to.)
211   if (!int_conn->locked()) {
212     LOG(LS_WARNING) << "Dropping packet: connection not locked";
213     return;
214   }
215 
216   // Forward this to the destination address into the connection.
217   RelayServerConnection* ext_conn = int_conn->binding()->GetExternalConnection(
218       int_conn->default_destination());
219   if (ext_conn && ext_conn->locked()) {
220     // TODO: Check the HMAC.
221     ext_conn->Send(bytes, size);
222   } else {
223     // This happens very often and is not an error.
224     LOG(LS_INFO) << "Dropping packet: no external connection";
225   }
226 }
227 
OnExternalPacket(rtc::AsyncPacketSocket * socket,const char * bytes,size_t size,const rtc::SocketAddress & remote_addr,const rtc::PacketTime & packet_time)228 void RelayServer::OnExternalPacket(
229     rtc::AsyncPacketSocket* socket, const char* bytes, size_t size,
230     const rtc::SocketAddress& remote_addr,
231     const rtc::PacketTime& packet_time) {
232 
233   // Get the address of the connection we just received on.
234   rtc::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
235   RTC_DCHECK(!ap.destination().IsNil());
236 
237   // If this connection already exists, then forward the traffic.
238   ConnectionMap::iterator piter = connections_.find(ap);
239   if (piter != connections_.end()) {
240     // TODO: Check the HMAC.
241     RelayServerConnection* ext_conn = piter->second;
242     RelayServerConnection* int_conn =
243         ext_conn->binding()->GetInternalConnection(
244             ext_conn->addr_pair().source());
245     RTC_DCHECK(int_conn != NULL);
246     int_conn->Send(bytes, size, ext_conn->addr_pair().source());
247     ext_conn->Lock();  // allow outgoing packets
248     return;
249   }
250 
251   // The first packet should always be a STUN / TURN packet.  If it isn't, then
252   // we should just ignore this packet.
253   RelayMessage msg;
254   rtc::ByteBufferReader buf(bytes, size);
255   if (!msg.Read(&buf)) {
256     LOG(LS_WARNING) << "Dropping packet: first packet not STUN";
257     return;
258   }
259 
260   // The initial packet should have a username (which identifies the binding).
261   const StunByteStringAttribute* username_attr =
262       msg.GetByteString(STUN_ATTR_USERNAME);
263   if (!username_attr) {
264     LOG(LS_WARNING) << "Dropping packet: no username";
265     return;
266   }
267 
268   uint32_t length =
269       std::min(static_cast<uint32_t>(username_attr->length()), USERNAME_LENGTH);
270   std::string username(username_attr->bytes(), length);
271   // TODO: Check the HMAC.
272 
273   // The binding should already be present.
274   BindingMap::iterator biter = bindings_.find(username);
275   if (biter == bindings_.end()) {
276     LOG(LS_WARNING) << "Dropping packet: no binding with username";
277     return;
278   }
279 
280   // Add this authenticted connection to the binding.
281   RelayServerConnection* ext_conn =
282       new RelayServerConnection(biter->second, ap, socket);
283   ext_conn->binding()->AddExternalConnection(ext_conn);
284   AddConnection(ext_conn);
285 
286   // We always know where external packets should be forwarded, so we can lock
287   // them from the beginning.
288   ext_conn->Lock();
289 
290   // Send this message on the appropriate internal connection.
291   RelayServerConnection* int_conn = ext_conn->binding()->GetInternalConnection(
292       ext_conn->addr_pair().source());
293   RTC_DCHECK(int_conn != NULL);
294   int_conn->Send(bytes, size, ext_conn->addr_pair().source());
295 }
296 
HandleStun(const char * bytes,size_t size,const rtc::SocketAddress & remote_addr,rtc::AsyncPacketSocket * socket,std::string * username,StunMessage * msg)297 bool RelayServer::HandleStun(
298     const char* bytes, size_t size, const rtc::SocketAddress& remote_addr,
299     rtc::AsyncPacketSocket* socket, std::string* username,
300     StunMessage* msg) {
301 
302   // Parse this into a stun message. Eat the message if this fails.
303   rtc::ByteBufferReader buf(bytes, size);
304   if (!msg->Read(&buf)) {
305     return false;
306   }
307 
308   // The initial packet should have a username (which identifies the binding).
309   const StunByteStringAttribute* username_attr =
310       msg->GetByteString(STUN_ATTR_USERNAME);
311   if (!username_attr) {
312     SendStunError(*msg, socket, remote_addr, 432, "Missing Username", "");
313     return false;
314   }
315 
316   // Record the username if requested.
317   if (username)
318     username->append(username_attr->bytes(), username_attr->length());
319 
320   // TODO: Check for unknown attributes (<= 0x7fff)
321 
322   return true;
323 }
324 
HandleStunAllocate(const char * bytes,size_t size,const rtc::SocketAddressPair & ap,rtc::AsyncPacketSocket * socket)325 void RelayServer::HandleStunAllocate(
326     const char* bytes, size_t size, const rtc::SocketAddressPair& ap,
327     rtc::AsyncPacketSocket* socket) {
328 
329   // Make sure this is a valid STUN request.
330   RelayMessage request;
331   std::string username;
332   if (!HandleStun(bytes, size, ap.source(), socket, &username, &request))
333     return;
334 
335   // Make sure this is a an allocate request.
336   if (request.type() != STUN_ALLOCATE_REQUEST) {
337     SendStunError(request,
338                   socket,
339                   ap.source(),
340                   600,
341                   "Operation Not Supported",
342                   "");
343     return;
344   }
345 
346   // TODO: Check the HMAC.
347 
348   // Find or create the binding for this username.
349 
350   RelayServerBinding* binding;
351 
352   BindingMap::iterator biter = bindings_.find(username);
353   if (biter != bindings_.end()) {
354     binding = biter->second;
355   } else {
356     // NOTE: In the future, bindings will be created by the bot only.  This
357     //       else-branch will then disappear.
358 
359     // Compute the appropriate lifetime for this binding.
360     int lifetime = MAX_LIFETIME;
361     const StunUInt32Attribute* lifetime_attr =
362         request.GetUInt32(STUN_ATTR_LIFETIME);
363     if (lifetime_attr)
364       lifetime =
365           std::min(lifetime, static_cast<int>(lifetime_attr->value() * 1000));
366 
367     binding = new RelayServerBinding(this, username, "0", lifetime);
368     binding->SignalTimeout.connect(this, &RelayServer::OnTimeout);
369     bindings_[username] = binding;
370 
371     if (log_bindings_) {
372       LOG(LS_INFO) << "Added new binding " << username << ", "
373                    << bindings_.size() << " total";
374     }
375   }
376 
377   // Add this connection to the binding.  It starts out unlocked.
378   RelayServerConnection* int_conn =
379       new RelayServerConnection(binding, ap, socket);
380   binding->AddInternalConnection(int_conn);
381   AddConnection(int_conn);
382 
383   // Now that we have a connection, this other method takes over.
384   HandleStunAllocate(int_conn, request);
385 }
386 
HandleStun(RelayServerConnection * int_conn,const char * bytes,size_t size)387 void RelayServer::HandleStun(
388     RelayServerConnection* int_conn, const char* bytes, size_t size) {
389 
390   // Make sure this is a valid STUN request.
391   RelayMessage request;
392   std::string username;
393   if (!HandleStun(bytes, size, int_conn->addr_pair().source(),
394                   int_conn->socket(), &username, &request))
395     return;
396 
397   // Make sure the username is the one were were expecting.
398   if (username != int_conn->binding()->username()) {
399     int_conn->SendStunError(request, 430, "Stale Credentials");
400     return;
401   }
402 
403   // TODO: Check the HMAC.
404 
405   // Send this request to the appropriate handler.
406   if (request.type() == STUN_SEND_REQUEST)
407     HandleStunSend(int_conn, request);
408   else if (request.type() == STUN_ALLOCATE_REQUEST)
409     HandleStunAllocate(int_conn, request);
410   else
411     int_conn->SendStunError(request, 600, "Operation Not Supported");
412 }
413 
HandleStunAllocate(RelayServerConnection * int_conn,const StunMessage & request)414 void RelayServer::HandleStunAllocate(
415     RelayServerConnection* int_conn, const StunMessage& request) {
416 
417   // Create a response message that includes an address with which external
418   // clients can communicate.
419 
420   RelayMessage response;
421   response.SetType(STUN_ALLOCATE_RESPONSE);
422   response.SetTransactionID(request.transaction_id());
423 
424   StunByteStringAttribute* magic_cookie_attr =
425       StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
426   magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
427                                int_conn->binding()->magic_cookie().size());
428   response.AddAttribute(magic_cookie_attr);
429 
430   size_t index = rand() % external_sockets_.size();
431   rtc::SocketAddress ext_addr =
432       external_sockets_[index]->GetLocalAddress();
433 
434   StunAddressAttribute* addr_attr =
435       StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
436   addr_attr->SetIP(ext_addr.ipaddr());
437   addr_attr->SetPort(ext_addr.port());
438   response.AddAttribute(addr_attr);
439 
440   StunUInt32Attribute* res_lifetime_attr =
441       StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
442   res_lifetime_attr->SetValue(int_conn->binding()->lifetime() / 1000);
443   response.AddAttribute(res_lifetime_attr);
444 
445   // TODO: Support transport-prefs (preallocate RTCP port).
446   // TODO: Support bandwidth restrictions.
447   // TODO: Add message integrity check.
448 
449   // Send a response to the caller.
450   int_conn->SendStun(response);
451 }
452 
HandleStunSend(RelayServerConnection * int_conn,const StunMessage & request)453 void RelayServer::HandleStunSend(
454     RelayServerConnection* int_conn, const StunMessage& request) {
455 
456   const StunAddressAttribute* addr_attr =
457       request.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
458   if (!addr_attr) {
459     int_conn->SendStunError(request, 400, "Bad Request");
460     return;
461   }
462 
463   const StunByteStringAttribute* data_attr =
464       request.GetByteString(STUN_ATTR_DATA);
465   if (!data_attr) {
466     int_conn->SendStunError(request, 400, "Bad Request");
467     return;
468   }
469 
470   rtc::SocketAddress ext_addr(addr_attr->ipaddr(), addr_attr->port());
471   RelayServerConnection* ext_conn =
472       int_conn->binding()->GetExternalConnection(ext_addr);
473   if (!ext_conn) {
474     // Create a new connection to establish the relationship with this binding.
475     RTC_DCHECK(external_sockets_.size() == 1);
476     rtc::AsyncPacketSocket* socket = external_sockets_[0];
477     rtc::SocketAddressPair ap(ext_addr, socket->GetLocalAddress());
478     ext_conn = new RelayServerConnection(int_conn->binding(), ap, socket);
479     ext_conn->binding()->AddExternalConnection(ext_conn);
480     AddConnection(ext_conn);
481   }
482 
483   // If this connection has pinged us, then allow outgoing traffic.
484   if (ext_conn->locked())
485     ext_conn->Send(data_attr->bytes(), data_attr->length());
486 
487   const StunUInt32Attribute* options_attr =
488       request.GetUInt32(STUN_ATTR_OPTIONS);
489   if (options_attr && (options_attr->value() & 0x01)) {
490     int_conn->set_default_destination(ext_addr);
491     int_conn->Lock();
492 
493     RelayMessage response;
494     response.SetType(STUN_SEND_RESPONSE);
495     response.SetTransactionID(request.transaction_id());
496 
497     StunByteStringAttribute* magic_cookie_attr =
498         StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
499     magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
500                                  int_conn->binding()->magic_cookie().size());
501     response.AddAttribute(magic_cookie_attr);
502 
503     StunUInt32Attribute* options2_attr =
504       StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS);
505     options2_attr->SetValue(0x01);
506     response.AddAttribute(options2_attr);
507 
508     int_conn->SendStun(response);
509   }
510 }
511 
AddConnection(RelayServerConnection * conn)512 void RelayServer::AddConnection(RelayServerConnection* conn) {
513   RTC_DCHECK(connections_.find(conn->addr_pair()) == connections_.end());
514   connections_[conn->addr_pair()] = conn;
515 }
516 
RemoveConnection(RelayServerConnection * conn)517 void RelayServer::RemoveConnection(RelayServerConnection* conn) {
518   ConnectionMap::iterator iter = connections_.find(conn->addr_pair());
519   RTC_DCHECK(iter != connections_.end());
520   connections_.erase(iter);
521 }
522 
RemoveBinding(RelayServerBinding * binding)523 void RelayServer::RemoveBinding(RelayServerBinding* binding) {
524   BindingMap::iterator iter = bindings_.find(binding->username());
525   RTC_DCHECK(iter != bindings_.end());
526   bindings_.erase(iter);
527 
528   if (log_bindings_) {
529     LOG(LS_INFO) << "Removed binding " << binding->username() << ", "
530                  << bindings_.size() << " remaining";
531   }
532 }
533 
OnMessage(rtc::Message * pmsg)534 void RelayServer::OnMessage(rtc::Message *pmsg) {
535   static const uint32_t kMessageAcceptConnection = 1;
536   RTC_DCHECK(pmsg->message_id == kMessageAcceptConnection);
537 
538   rtc::MessageData* data = pmsg->pdata;
539   rtc::AsyncSocket* socket =
540       static_cast <rtc::TypedMessageData<rtc::AsyncSocket*>*>
541       (data)->data();
542   AcceptConnection(socket);
543   delete data;
544 }
545 
OnTimeout(RelayServerBinding * binding)546 void RelayServer::OnTimeout(RelayServerBinding* binding) {
547   // This call will result in all of the necessary clean-up. We can't call
548   // delete here, because you can't delete an object that is signaling you.
549   thread_->Dispose(binding);
550 }
551 
AcceptConnection(rtc::AsyncSocket * server_socket)552 void RelayServer::AcceptConnection(rtc::AsyncSocket* server_socket) {
553   // Check if someone is trying to connect to us.
554   rtc::SocketAddress accept_addr;
555   rtc::AsyncSocket* accepted_socket =
556       server_socket->Accept(&accept_addr);
557   if (accepted_socket != NULL) {
558     // We had someone trying to connect, now check which protocol to
559     // use and create a packet socket.
560     RTC_DCHECK(server_sockets_[server_socket] == cricket::PROTO_TCP ||
561                server_sockets_[server_socket] == cricket::PROTO_SSLTCP);
562     if (server_sockets_[server_socket] == cricket::PROTO_SSLTCP) {
563       accepted_socket = new rtc::AsyncSSLServerSocket(accepted_socket);
564     }
565     rtc::AsyncTCPSocket* tcp_socket =
566         new rtc::AsyncTCPSocket(accepted_socket, false);
567 
568     // Finally add the socket so it can start communicating with the client.
569     AddInternalSocket(tcp_socket);
570   }
571 }
572 
RelayServerConnection(RelayServerBinding * binding,const rtc::SocketAddressPair & addrs,rtc::AsyncPacketSocket * socket)573 RelayServerConnection::RelayServerConnection(
574     RelayServerBinding* binding, const rtc::SocketAddressPair& addrs,
575     rtc::AsyncPacketSocket* socket)
576   : binding_(binding), addr_pair_(addrs), socket_(socket), locked_(false) {
577   // The creation of a new connection constitutes a use of the binding.
578   binding_->NoteUsed();
579 }
580 
~RelayServerConnection()581 RelayServerConnection::~RelayServerConnection() {
582   // Remove this connection from the server's map (if it exists there).
583   binding_->server()->RemoveConnection(this);
584 }
585 
Send(const char * data,size_t size)586 void RelayServerConnection::Send(const char* data, size_t size) {
587   // Note that the binding has been used again.
588   binding_->NoteUsed();
589 
590   cricket::Send(socket_, data, size, addr_pair_.source());
591 }
592 
Send(const char * data,size_t size,const rtc::SocketAddress & from_addr)593 void RelayServerConnection::Send(
594     const char* data, size_t size, const rtc::SocketAddress& from_addr) {
595   // If the from address is known to the client, we don't need to send it.
596   if (locked() && (from_addr == default_dest_)) {
597     Send(data, size);
598     return;
599   }
600 
601   // Wrap the given data in a data-indication packet.
602 
603   RelayMessage msg;
604   msg.SetType(STUN_DATA_INDICATION);
605 
606   StunByteStringAttribute* magic_cookie_attr =
607       StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
608   magic_cookie_attr->CopyBytes(binding_->magic_cookie().c_str(),
609                                binding_->magic_cookie().size());
610   msg.AddAttribute(magic_cookie_attr);
611 
612   StunAddressAttribute* addr_attr =
613       StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
614   addr_attr->SetIP(from_addr.ipaddr());
615   addr_attr->SetPort(from_addr.port());
616   msg.AddAttribute(addr_attr);
617 
618   StunByteStringAttribute* data_attr =
619       StunAttribute::CreateByteString(STUN_ATTR_DATA);
620   RTC_DCHECK(size <= 65536);
621   data_attr->CopyBytes(data, uint16_t(size));
622   msg.AddAttribute(data_attr);
623 
624   SendStun(msg);
625 }
626 
SendStun(const StunMessage & msg)627 void RelayServerConnection::SendStun(const StunMessage& msg) {
628   // Note that the binding has been used again.
629   binding_->NoteUsed();
630 
631   cricket::SendStun(msg, socket_, addr_pair_.source());
632 }
633 
SendStunError(const StunMessage & request,int error_code,const char * error_desc)634 void RelayServerConnection::SendStunError(
635       const StunMessage& request, int error_code, const char* error_desc) {
636   // An error does not indicate use.  If no legitimate use off the binding
637   // occurs, we want it to be cleaned up even if errors are still occuring.
638 
639   cricket::SendStunError(
640       request, socket_, addr_pair_.source(), error_code, error_desc,
641       binding_->magic_cookie());
642 }
643 
Lock()644 void RelayServerConnection::Lock() {
645   locked_ = true;
646 }
647 
Unlock()648 void RelayServerConnection::Unlock() {
649   locked_ = false;
650 }
651 
652 // IDs used for posted messages:
653 const uint32_t MSG_LIFETIME_TIMER = 1;
654 
RelayServerBinding(RelayServer * server,const std::string & username,const std::string & password,int lifetime)655 RelayServerBinding::RelayServerBinding(RelayServer* server,
656                                        const std::string& username,
657                                        const std::string& password,
658                                        int lifetime)
659     : server_(server),
660       username_(username),
661       password_(password),
662       lifetime_(lifetime) {
663   // For now, every connection uses the standard magic cookie value.
664   magic_cookie_.append(
665       reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
666       sizeof(TURN_MAGIC_COOKIE_VALUE));
667 
668   // Initialize the last-used time to now.
669   NoteUsed();
670 
671   // Set the first timeout check.
672   server_->thread()->PostDelayed(RTC_FROM_HERE, lifetime_, this,
673                                  MSG_LIFETIME_TIMER);
674 }
675 
~RelayServerBinding()676 RelayServerBinding::~RelayServerBinding() {
677   // Clear the outstanding timeout check.
678   server_->thread()->Clear(this);
679 
680   // Clean up all of the connections.
681   for (size_t i = 0; i < internal_connections_.size(); ++i)
682     delete internal_connections_[i];
683   for (size_t i = 0; i < external_connections_.size(); ++i)
684     delete external_connections_[i];
685 
686   // Remove this binding from the server's map.
687   server_->RemoveBinding(this);
688 }
689 
AddInternalConnection(RelayServerConnection * conn)690 void RelayServerBinding::AddInternalConnection(RelayServerConnection* conn) {
691   internal_connections_.push_back(conn);
692 }
693 
AddExternalConnection(RelayServerConnection * conn)694 void RelayServerBinding::AddExternalConnection(RelayServerConnection* conn) {
695   external_connections_.push_back(conn);
696 }
697 
NoteUsed()698 void RelayServerBinding::NoteUsed() {
699   last_used_ = rtc::TimeMillis();
700 }
701 
HasMagicCookie(const char * bytes,size_t size) const702 bool RelayServerBinding::HasMagicCookie(const char* bytes, size_t size) const {
703   if (size < 24 + magic_cookie_.size()) {
704     return false;
705   } else {
706     return memcmp(bytes + 24, magic_cookie_.c_str(), magic_cookie_.size()) == 0;
707   }
708 }
709 
GetInternalConnection(const rtc::SocketAddress & ext_addr)710 RelayServerConnection* RelayServerBinding::GetInternalConnection(
711     const rtc::SocketAddress& ext_addr) {
712 
713   // Look for an internal connection that is locked to this address.
714   for (size_t i = 0; i < internal_connections_.size(); ++i) {
715     if (internal_connections_[i]->locked() &&
716         (ext_addr == internal_connections_[i]->default_destination()))
717       return internal_connections_[i];
718   }
719 
720   // If one was not found, we send to the first connection.
721   RTC_DCHECK(internal_connections_.size() > 0);
722   return internal_connections_[0];
723 }
724 
GetExternalConnection(const rtc::SocketAddress & ext_addr)725 RelayServerConnection* RelayServerBinding::GetExternalConnection(
726     const rtc::SocketAddress& ext_addr) {
727   for (size_t i = 0; i < external_connections_.size(); ++i) {
728     if (ext_addr == external_connections_[i]->addr_pair().source())
729       return external_connections_[i];
730   }
731   return 0;
732 }
733 
OnMessage(rtc::Message * pmsg)734 void RelayServerBinding::OnMessage(rtc::Message *pmsg) {
735   if (pmsg->message_id == MSG_LIFETIME_TIMER) {
736     RTC_DCHECK(!pmsg->pdata);
737 
738     // If the lifetime timeout has been exceeded, then send a signal.
739     // Otherwise, just keep waiting.
740     if (rtc::TimeMillis() >= last_used_ + lifetime_) {
741       LOG(LS_INFO) << "Expiring binding " << username_;
742       SignalTimeout(this);
743     } else {
744       server_->thread()->PostDelayed(RTC_FROM_HERE, lifetime_, this,
745                                      MSG_LIFETIME_TIMER);
746     }
747 
748   } else {
749     RTC_NOTREACHED();
750   }
751 }
752 
753 }  // namespace cricket
754