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/base/asyncpacketsocket.h" 29 #include "talk/base/helpers.h" 30 #include "talk/base/logging.h" 31 #include "talk/p2p/base/relayport.h" 32 33 namespace cricket { 34 35 static const uint32 kMessageConnectTimeout = 1; 36 static const int kKeepAliveDelay = 10 * 60 * 1000; 37 static const int kRetryTimeout = 50 * 1000; // ICE says 50 secs 38 // How long to wait for a socket to connect to remote host in milliseconds 39 // before trying another connection. 40 static const int kSoftConnectTimeoutMs = 3 * 1000; 41 42 // Handles a connection to one address/port/protocol combination for a 43 // particular RelayEntry. 44 class RelayConnection : public sigslot::has_slots<> { 45 public: 46 RelayConnection(const ProtocolAddress* protocol_address, 47 talk_base::AsyncPacketSocket* socket, 48 talk_base::Thread* thread); 49 ~RelayConnection(); 50 talk_base::AsyncPacketSocket* socket() const { return socket_; } 51 52 const ProtocolAddress* protocol_address() { 53 return protocol_address_; 54 } 55 56 talk_base::SocketAddress GetAddress() const { 57 return protocol_address_->address; 58 } 59 60 ProtocolType GetProtocol() const { 61 return protocol_address_->proto; 62 } 63 64 int SetSocketOption(talk_base::Socket::Option opt, int value); 65 66 // Validates a response to a STUN allocate request. 67 bool CheckResponse(StunMessage* msg); 68 69 // Sends data to the relay server. 70 int Send(const void* pv, size_t cb); 71 72 // Sends a STUN allocate request message to the relay server. 73 void SendAllocateRequest(RelayEntry* entry, int delay); 74 75 // Return the latest error generated by the socket. 76 int GetError() { return socket_->GetError(); } 77 78 // Called on behalf of a StunRequest to write data to the socket. This is 79 // already STUN intended for the server, so no wrapping is necessary. 80 void OnSendPacket(const void* data, size_t size, StunRequest* req); 81 82 private: 83 talk_base::AsyncPacketSocket* socket_; 84 const ProtocolAddress* protocol_address_; 85 StunRequestManager *request_manager_; 86 }; 87 88 // Manages a number of connections to the relayserver, one for each 89 // available protocol. We aim to use each connection for only a 90 // specific destination address so that we can avoid wrapping every 91 // packet in a STUN send / data indication. 92 class RelayEntry : public talk_base::MessageHandler, 93 public sigslot::has_slots<> { 94 public: 95 RelayEntry(RelayPort* port, const talk_base::SocketAddress& ext_addr); 96 ~RelayEntry(); 97 98 RelayPort* port() { return port_; } 99 100 const talk_base::SocketAddress& address() const { return ext_addr_; } 101 void set_address(const talk_base::SocketAddress& addr) { ext_addr_ = addr; } 102 103 bool connected() const { return connected_; } 104 bool locked() const { return locked_; } 105 106 // Returns the last error on the socket of this entry. 107 int GetError(); 108 109 // Returns the most preferred connection of the given 110 // ones. Connections are rated based on protocol in the order of: 111 // UDP, TCP and SSLTCP, where UDP is the most preferred protocol 112 static RelayConnection* GetBestConnection(RelayConnection* conn1, 113 RelayConnection* conn2); 114 115 // Sends the STUN requests to the server to initiate this connection. 116 void Connect(); 117 118 // Called when this entry becomes connected. The address given is the one 119 // exposed to the outside world on the relay server. 120 void OnConnect(const talk_base::SocketAddress& mapped_addr, 121 RelayConnection* socket); 122 123 // Sends a packet to the given destination address using the socket of this 124 // entry. This will wrap the packet in STUN if necessary. 125 int SendTo(const void* data, size_t size, 126 const talk_base::SocketAddress& addr); 127 128 // Schedules a keep-alive allocate request. 129 void ScheduleKeepAlive(); 130 131 void SetServerIndex(size_t sindex) { server_index_ = sindex; } 132 133 // Sets this option on the socket of each connection. 134 int SetSocketOption(talk_base::Socket::Option opt, int value); 135 136 size_t ServerIndex() const { return server_index_; } 137 138 // Try a different server address 139 void HandleConnectFailure(talk_base::AsyncPacketSocket* socket); 140 141 // Implementation of the MessageHandler Interface. 142 virtual void OnMessage(talk_base::Message *pmsg); 143 144 private: 145 RelayPort* port_; 146 talk_base::SocketAddress ext_addr_; 147 size_t server_index_; 148 bool connected_; 149 bool locked_; 150 RelayConnection* current_connection_; 151 152 // Called when a TCP connection is established or fails 153 void OnSocketConnect(talk_base::AsyncPacketSocket* socket); 154 void OnSocketClose(talk_base::AsyncPacketSocket* socket, int error); 155 156 // Called when a packet is received on this socket. 157 void OnReadPacket(talk_base::AsyncPacketSocket* socket, 158 const char* data, size_t size, 159 const talk_base::SocketAddress& remote_addr); 160 161 // Sends the given data on the socket to the server with no wrapping. This 162 // returns the number of bytes written or -1 if an error occurred. 163 int SendPacket(const void* data, size_t size); 164 }; 165 166 // Handles an allocate request for a particular RelayEntry. 167 class AllocateRequest : public StunRequest { 168 public: 169 AllocateRequest(RelayEntry* entry, RelayConnection* connection); 170 virtual ~AllocateRequest() {} 171 172 virtual void Prepare(StunMessage* request); 173 174 virtual int GetNextDelay(); 175 176 virtual void OnResponse(StunMessage* response); 177 virtual void OnErrorResponse(StunMessage* response); 178 virtual void OnTimeout(); 179 180 private: 181 RelayEntry* entry_; 182 RelayConnection* connection_; 183 uint32 start_time_; 184 }; 185 186 const std::string RELAY_PORT_TYPE("relay"); 187 188 RelayPort::RelayPort( 189 talk_base::Thread* thread, talk_base::PacketSocketFactory* factory, 190 talk_base::Network* network, uint32 ip, int min_port, int max_port, 191 const std::string& username, const std::string& password, 192 const std::string& magic_cookie) 193 : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port), 194 ready_(false), 195 magic_cookie_(magic_cookie), 196 error_(0) { 197 entries_.push_back( 198 new RelayEntry(this, talk_base::SocketAddress())); 199 200 set_username_fragment(username); 201 set_password(password); 202 if (magic_cookie_.size() == 0) 203 magic_cookie_.append(STUN_MAGIC_COOKIE_VALUE, 4); 204 } 205 206 RelayPort::~RelayPort() { 207 for (size_t i = 0; i < entries_.size(); ++i) 208 delete entries_[i]; 209 thread_->Clear(this); 210 } 211 212 void RelayPort::AddServerAddress(const ProtocolAddress& addr) { 213 // Since HTTP proxies usually only allow 443, 214 // let's up the priority on PROTO_SSLTCP 215 if (addr.proto == PROTO_SSLTCP && 216 (proxy().type == talk_base::PROXY_HTTPS || 217 proxy().type == talk_base::PROXY_UNKNOWN)) { 218 server_addr_.push_front(addr); 219 } else { 220 server_addr_.push_back(addr); 221 } 222 } 223 224 void RelayPort::AddExternalAddress(const ProtocolAddress& addr) { 225 std::string proto_name = ProtoToString(addr.proto); 226 for (std::vector<Candidate>::const_iterator it = candidates().begin(); 227 it != candidates().end(); ++it) { 228 if ((it->address() == addr.address) && (it->protocol() == proto_name)) { 229 LOG(INFO) << "Redundant relay address: " << proto_name 230 << " @ " << addr.address.ToString(); 231 return; 232 } 233 } 234 AddAddress(addr.address, proto_name, false); 235 } 236 237 void RelayPort::SetReady() { 238 if (!ready_) { 239 ready_ = true; 240 SignalAddressReady(this); 241 } 242 } 243 244 const ProtocolAddress * RelayPort::ServerAddress(size_t index) const { 245 if (index < server_addr_.size()) 246 return &server_addr_[index]; 247 return NULL; 248 } 249 250 bool RelayPort::HasMagicCookie(const char* data, size_t size) { 251 if (size < 24 + magic_cookie_.size()) { 252 return false; 253 } else { 254 return 0 == std::memcmp(data + 24, 255 magic_cookie_.c_str(), 256 magic_cookie_.size()); 257 } 258 } 259 260 void RelayPort::PrepareAddress() { 261 // We initiate a connect on the first entry. If this completes, it will fill 262 // in the server address as the address of this port. 263 ASSERT(entries_.size() == 1); 264 entries_[0]->Connect(); 265 ready_ = false; 266 } 267 268 Connection* RelayPort::CreateConnection(const Candidate& address, 269 CandidateOrigin origin) { 270 // We only create conns to non-udp sockets if they are incoming on this port 271 if ((address.protocol() != "udp") && (origin != ORIGIN_THIS_PORT)) { 272 return 0; 273 } 274 275 // We don't support loopback on relays 276 if (address.type() == type()) { 277 return 0; 278 } 279 280 size_t index = 0; 281 for (size_t i = 0; i < candidates().size(); ++i) { 282 const Candidate& local = candidates()[i]; 283 if (local.protocol() == address.protocol()) { 284 index = i; 285 break; 286 } 287 } 288 289 Connection * conn = new ProxyConnection(this, index, address); 290 AddConnection(conn); 291 return conn; 292 } 293 294 int RelayPort::SendTo(const void* data, size_t size, 295 const talk_base::SocketAddress& addr, bool payload) { 296 // Try to find an entry for this specific address. Note that the first entry 297 // created was not given an address initially, so it can be set to the first 298 // address that comes along. 299 RelayEntry* entry = 0; 300 301 for (size_t i = 0; i < entries_.size(); ++i) { 302 if (entries_[i]->address().IsAny() && payload) { 303 entry = entries_[i]; 304 entry->set_address(addr); 305 break; 306 } else if (entries_[i]->address() == addr) { 307 entry = entries_[i]; 308 break; 309 } 310 } 311 312 // If we did not find one, then we make a new one. This will not be useable 313 // until it becomes connected, however. 314 if (!entry && payload) { 315 entry = new RelayEntry(this, addr); 316 if (!entries_.empty()) { 317 entry->SetServerIndex(entries_[0]->ServerIndex()); 318 } 319 entry->Connect(); 320 entries_.push_back(entry); 321 } 322 323 // If the entry is connected, then we can send on it (though wrapping may 324 // still be necessary). Otherwise, we can't yet use this connection, so we 325 // default to the first one. 326 if (!entry || !entry->connected()) { 327 ASSERT(!entries_.empty()); 328 entry = entries_[0]; 329 if (!entry->connected()) { 330 error_ = EWOULDBLOCK; 331 return SOCKET_ERROR; 332 } 333 } 334 335 // Send the actual contents to the server using the usual mechanism. 336 int sent = entry->SendTo(data, size, addr); 337 if (sent <= 0) { 338 ASSERT(sent < 0); 339 error_ = entry->GetError(); 340 return SOCKET_ERROR; 341 } 342 // The caller of the function is expecting the number of user data bytes, 343 // rather than the size of the packet. 344 return size; 345 } 346 347 int RelayPort::SetOption(talk_base::Socket::Option opt, int value) { 348 int result = 0; 349 for (size_t i = 0; i < entries_.size(); ++i) { 350 if (entries_[i]->SetSocketOption(opt, value) < 0) { 351 result = -1; 352 error_ = entries_[i]->GetError(); 353 } 354 } 355 options_.push_back(OptionValue(opt, value)); 356 return result; 357 } 358 359 int RelayPort::GetError() { 360 return error_; 361 } 362 363 void RelayPort::OnReadPacket( 364 const char* data, size_t size, 365 const talk_base::SocketAddress& remote_addr) { 366 if (Connection* conn = GetConnection(remote_addr)) { 367 conn->OnReadPacket(data, size); 368 } else { 369 Port::OnReadPacket(data, size, remote_addr); 370 } 371 } 372 373 RelayConnection::RelayConnection(const ProtocolAddress* protocol_address, 374 talk_base::AsyncPacketSocket* socket, 375 talk_base::Thread* thread) 376 : socket_(socket), 377 protocol_address_(protocol_address) { 378 request_manager_ = new StunRequestManager(thread); 379 request_manager_->SignalSendPacket.connect(this, 380 &RelayConnection::OnSendPacket); 381 } 382 383 RelayConnection::~RelayConnection() { 384 delete request_manager_; 385 delete socket_; 386 } 387 388 int RelayConnection::SetSocketOption(talk_base::Socket::Option opt, 389 int value) { 390 if (socket_) { 391 return socket_->SetOption(opt, value); 392 } 393 return 0; 394 } 395 396 bool RelayConnection::CheckResponse(StunMessage* msg) { 397 return request_manager_->CheckResponse(msg); 398 } 399 400 void RelayConnection::OnSendPacket(const void* data, size_t size, 401 StunRequest* req) { 402 int sent = socket_->SendTo(data, size, GetAddress()); 403 if (sent <= 0) { 404 LOG(LS_VERBOSE) << "OnSendPacket: failed sending to " << GetAddress() << 405 std::strerror(socket_->GetError()); 406 ASSERT(sent < 0); 407 } 408 } 409 410 int RelayConnection::Send(const void* pv, size_t cb) { 411 return socket_->SendTo(pv, cb, GetAddress()); 412 } 413 414 void RelayConnection::SendAllocateRequest(RelayEntry* entry, int delay) { 415 request_manager_->SendDelayed(new AllocateRequest(entry, this), delay); 416 } 417 418 RelayEntry::RelayEntry(RelayPort* port, 419 const talk_base::SocketAddress& ext_addr) 420 : port_(port), ext_addr_(ext_addr), 421 server_index_(0), connected_(false), locked_(false), 422 current_connection_(NULL) { 423 } 424 425 RelayEntry::~RelayEntry() { 426 // Remove all RelayConnections and dispose sockets. 427 delete current_connection_; 428 current_connection_ = NULL; 429 } 430 431 void RelayEntry::Connect() { 432 // If we're already connected, return. 433 if (connected_) 434 return; 435 436 // If we've exhausted all options, bail out. 437 const ProtocolAddress* ra = port()->ServerAddress(server_index_); 438 if (!ra) { 439 LOG(LS_WARNING) << "No more relay addresses left to try"; 440 return; 441 } 442 443 // Remove any previous connection. 444 if (current_connection_) { 445 port()->thread()->Dispose(current_connection_); 446 current_connection_ = NULL; 447 } 448 449 // Try to set up our new socket. 450 LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto) << 451 " @ " << ra->address.ToString(); 452 453 talk_base::AsyncPacketSocket* socket = NULL; 454 455 if (ra->proto == PROTO_UDP) { 456 // UDP sockets are simple. 457 socket = port_->socket_factory()->CreateUdpSocket( 458 talk_base::SocketAddress(port_->ip_, 0), 459 port_->min_port_, port_->max_port_); 460 } else if (ra->proto == PROTO_TCP || ra->proto == PROTO_SSLTCP) { 461 socket = port_->socket_factory()->CreateClientTcpSocket( 462 talk_base::SocketAddress(port_->ip_, 0), ra->address, 463 port_->proxy(), port_->user_agent(), ra->proto == PROTO_SSLTCP); 464 } else { 465 LOG(LS_WARNING) << "Unknown protocol (" << ra->proto << ")"; 466 } 467 468 if (!socket) { 469 LOG(LS_WARNING) << "Socket creation failed"; 470 } 471 472 // If we failed to get a socket, move on to the next protocol. 473 if (!socket) { 474 port()->thread()->Post(this, kMessageConnectTimeout); 475 return; 476 } 477 478 // Otherwise, create the new connection and configure any socket options. 479 socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket); 480 current_connection_ = new RelayConnection(ra, socket, port()->thread()); 481 for (size_t i = 0; i < port_->options().size(); ++i) { 482 current_connection_->SetSocketOption(port_->options()[i].first, 483 port_->options()[i].second); 484 } 485 486 // If we're trying UDP, start binding requests. 487 // If we're trying TCP, wait for connection with a fixed timeout. 488 if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) { 489 socket->SignalClose.connect(this, &RelayEntry::OnSocketClose); 490 socket->SignalConnect.connect(this, &RelayEntry::OnSocketConnect); 491 port()->thread()->PostDelayed(kSoftConnectTimeoutMs, this, 492 kMessageConnectTimeout); 493 } else { 494 current_connection_->SendAllocateRequest(this, 0); 495 } 496 } 497 498 int RelayEntry::GetError() { 499 if (current_connection_ != NULL) { 500 return current_connection_->GetError(); 501 } 502 return 0; 503 } 504 505 RelayConnection* RelayEntry::GetBestConnection(RelayConnection* conn1, 506 RelayConnection* conn2) { 507 return conn1->GetProtocol() <= conn2->GetProtocol() ? conn1 : conn2; 508 } 509 510 void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr, 511 RelayConnection* connection) { 512 // We are connected, notify our parent. 513 ProtocolType proto = PROTO_UDP; 514 LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto) 515 << " @ " << mapped_addr.ToString(); 516 connected_ = true; 517 518 port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto)); 519 port_->SetReady(); 520 } 521 522 int RelayEntry::SendTo(const void* data, size_t size, 523 const talk_base::SocketAddress& addr) { 524 // If this connection is locked to the address given, then we can send the 525 // packet with no wrapper. 526 if (locked_ && (ext_addr_ == addr)) 527 return SendPacket(data, size); 528 529 // Otherwise, we must wrap the given data in a STUN SEND request so that we 530 // can communicate the destination address to the server. 531 // 532 // Note that we do not use a StunRequest here. This is because there is 533 // likely no reason to resend this packet. If it is late, we just drop it. 534 // The next send to this address will try again. 535 536 StunMessage request; 537 request.SetType(STUN_SEND_REQUEST); 538 request.SetTransactionID(talk_base::CreateRandomString(16)); 539 540 StunByteStringAttribute* magic_cookie_attr = 541 StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); 542 magic_cookie_attr->CopyBytes(port_->magic_cookie().c_str(), 543 port_->magic_cookie().size()); 544 request.AddAttribute(magic_cookie_attr); 545 546 StunByteStringAttribute* username_attr = 547 StunAttribute::CreateByteString(STUN_ATTR_USERNAME); 548 username_attr->CopyBytes(port_->username_fragment().c_str(), 549 port_->username_fragment().size()); 550 request.AddAttribute(username_attr); 551 552 StunAddressAttribute* addr_attr = 553 StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS); 554 addr_attr->SetFamily(1); 555 addr_attr->SetIP(addr.ip()); 556 addr_attr->SetPort(addr.port()); 557 request.AddAttribute(addr_attr); 558 559 // Attempt to lock 560 if (ext_addr_ == addr) { 561 StunUInt32Attribute* options_attr = 562 StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS); 563 options_attr->SetValue(0x1); 564 request.AddAttribute(options_attr); 565 } 566 567 StunByteStringAttribute* data_attr = 568 StunAttribute::CreateByteString(STUN_ATTR_DATA); 569 data_attr->CopyBytes(data, size); 570 request.AddAttribute(data_attr); 571 572 // TODO: compute the HMAC. 573 574 talk_base::ByteBuffer buf; 575 request.Write(&buf); 576 577 return SendPacket(buf.Data(), buf.Length()); 578 } 579 580 void RelayEntry::ScheduleKeepAlive() { 581 if (current_connection_) { 582 current_connection_->SendAllocateRequest(this, kKeepAliveDelay); 583 } 584 } 585 586 int RelayEntry::SetSocketOption(talk_base::Socket::Option opt, int value) { 587 // Set the option on all available sockets. 588 int socket_error = 0; 589 if (current_connection_) { 590 socket_error = current_connection_->SetSocketOption(opt, value); 591 } 592 return socket_error; 593 } 594 595 void RelayEntry::HandleConnectFailure( 596 talk_base::AsyncPacketSocket* socket) { 597 // Make sure it's the current connection that has failed, it might 598 // be an old socked that has not yet been disposed. 599 if (!socket || socket == current_connection_->socket()) { 600 if (current_connection_) 601 port()->SignalConnectFailure(current_connection_->protocol_address()); 602 603 // Try to connect to the next server address. 604 server_index_ += 1; 605 Connect(); 606 } 607 } 608 609 void RelayEntry::OnMessage(talk_base::Message *pmsg) { 610 ASSERT(pmsg->message_id == kMessageConnectTimeout); 611 if (current_connection_) { 612 const ProtocolAddress* ra = current_connection_->protocol_address(); 613 LOG(LS_WARNING) << "Relay " << ra->proto << " connection to " << 614 ra->address << " timed out"; 615 616 // Currently we connect to each server address in sequence. If we 617 // have more addresses to try, treat this is an error and move on to 618 // the next address, otherwise give this connection more time and 619 // await the real timeout. 620 // 621 // TODO: Connect to servers in parallel to speed up connect time 622 // and to avoid giving up too early. 623 port_->SignalSoftTimeout(ra); 624 HandleConnectFailure(current_connection_->socket()); 625 } else { 626 HandleConnectFailure(NULL); 627 } 628 } 629 630 void RelayEntry::OnSocketConnect(talk_base::AsyncPacketSocket* socket) { 631 LOG(INFO) << "relay tcp connected to " << 632 socket->GetRemoteAddress().ToString(); 633 if (current_connection_ != NULL) { 634 current_connection_->SendAllocateRequest(this, 0); 635 } 636 } 637 638 void RelayEntry::OnSocketClose(talk_base::AsyncPacketSocket* socket, 639 int error) { 640 PLOG(LERROR, error) << "Relay connection failed: socket closed"; 641 HandleConnectFailure(socket); 642 } 643 644 void RelayEntry::OnReadPacket(talk_base::AsyncPacketSocket* socket, 645 const char* data, size_t size, 646 const talk_base::SocketAddress& remote_addr) { 647 // ASSERT(remote_addr == port_->server_addr()); 648 // TODO: are we worried about this? 649 650 if (current_connection_ == NULL || socket != current_connection_->socket()) { 651 // This packet comes from an unknown address. 652 LOG(WARNING) << "Dropping packet: unknown address"; 653 return; 654 } 655 656 // If the magic cookie is not present, then this is an unwrapped packet sent 657 // by the server, The actual remote address is the one we recorded. 658 if (!port_->HasMagicCookie(data, size)) { 659 if (locked_) { 660 port_->OnReadPacket(data, size, ext_addr_); 661 } else { 662 LOG(WARNING) << "Dropping packet: entry not locked"; 663 } 664 return; 665 } 666 667 talk_base::ByteBuffer buf(data, size); 668 StunMessage msg; 669 if (!msg.Read(&buf)) { 670 LOG(INFO) << "Incoming packet was not STUN"; 671 return; 672 } 673 674 // The incoming packet should be a STUN ALLOCATE response, SEND response, or 675 // DATA indication. 676 if (current_connection_->CheckResponse(&msg)) { 677 return; 678 } else if (msg.type() == STUN_SEND_RESPONSE) { 679 if (const StunUInt32Attribute* options_attr = 680 msg.GetUInt32(STUN_ATTR_OPTIONS)) { 681 if (options_attr->value() & 0x1) { 682 locked_ = true; 683 } 684 } 685 return; 686 } else if (msg.type() != STUN_DATA_INDICATION) { 687 LOG(INFO) << "Received BAD stun type from server: " << msg.type(); 688 return; 689 } 690 691 // This must be a data indication. 692 693 const StunAddressAttribute* addr_attr = 694 msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2); 695 if (!addr_attr) { 696 LOG(INFO) << "Data indication has no source address"; 697 return; 698 } else if (addr_attr->family() != 1) { 699 LOG(INFO) << "Source address has bad family"; 700 return; 701 } 702 703 talk_base::SocketAddress remote_addr2(addr_attr->ip(), addr_attr->port()); 704 705 const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA); 706 if (!data_attr) { 707 LOG(INFO) << "Data indication has no data"; 708 return; 709 } 710 711 // Process the actual data and remote address in the normal manner. 712 port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2); 713 } 714 715 int RelayEntry::SendPacket(const void* data, size_t size) { 716 int sent = 0; 717 if (current_connection_) { 718 // We are connected, no need to send packets anywere else than to 719 // the current connection. 720 sent = current_connection_->Send(data, size); 721 } 722 return sent; 723 } 724 725 AllocateRequest::AllocateRequest(RelayEntry* entry, 726 RelayConnection* connection) : 727 entry_(entry), connection_(connection) { 728 start_time_ = talk_base::Time(); 729 } 730 731 void AllocateRequest::Prepare(StunMessage* request) { 732 request->SetType(STUN_ALLOCATE_REQUEST); 733 734 StunByteStringAttribute* magic_cookie_attr = 735 StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE); 736 magic_cookie_attr->CopyBytes( 737 entry_->port()->magic_cookie().c_str(), 738 entry_->port()->magic_cookie().size()); 739 request->AddAttribute(magic_cookie_attr); 740 741 StunByteStringAttribute* username_attr = 742 StunAttribute::CreateByteString(STUN_ATTR_USERNAME); 743 username_attr->CopyBytes( 744 entry_->port()->username_fragment().c_str(), 745 entry_->port()->username_fragment().size()); 746 request->AddAttribute(username_attr); 747 } 748 749 int AllocateRequest::GetNextDelay() { 750 int delay = 100 * talk_base::_max(1 << count_, 2); 751 count_ += 1; 752 if (count_ == 5) 753 timeout_ = true; 754 return delay; 755 } 756 757 void AllocateRequest::OnResponse(StunMessage* response) { 758 const StunAddressAttribute* addr_attr = 759 response->GetAddress(STUN_ATTR_MAPPED_ADDRESS); 760 if (!addr_attr) { 761 LOG(INFO) << "Allocate response missing mapped address."; 762 } else if (addr_attr->family() != 1) { 763 LOG(INFO) << "Mapped address has bad family"; 764 } else { 765 talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port()); 766 entry_->OnConnect(addr, connection_); 767 } 768 769 // We will do a keep-alive regardless of whether this request suceeds. 770 // This should have almost no impact on network usage. 771 entry_->ScheduleKeepAlive(); 772 } 773 774 void AllocateRequest::OnErrorResponse(StunMessage* response) { 775 const StunErrorCodeAttribute* attr = response->GetErrorCode(); 776 if (!attr) { 777 LOG(INFO) << "Bad allocate response error code"; 778 } else { 779 LOG(INFO) << "Allocate error response:" 780 << " code=" << static_cast<int>(attr->error_code()) 781 << " reason='" << attr->reason() << "'"; 782 } 783 784 if (talk_base::TimeSince(start_time_) <= kRetryTimeout) 785 entry_->ScheduleKeepAlive(); 786 } 787 788 void AllocateRequest::OnTimeout() { 789 LOG(INFO) << "Allocate request timed out"; 790 entry_->HandleConnectFailure(connection_->socket()); 791 } 792 793 } // namespace cricket 794