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