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