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