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