1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/socket/tcp_client_socket.h" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <netdb.h> 10 #include <sys/socket.h> 11 #include <netinet/tcp.h> 12 #if defined(OS_POSIX) 13 #include <netinet/in.h> 14 #endif 15 16 #include "base/logging.h" 17 #include "base/message_loop/message_loop.h" 18 #include "base/metrics/histogram.h" 19 #include "base/metrics/stats_counters.h" 20 #include "base/posix/eintr_wrapper.h" 21 #include "base/strings/string_util.h" 22 #include "net/base/connection_type_histograms.h" 23 #include "net/base/io_buffer.h" 24 #include "net/base/ip_endpoint.h" 25 #include "net/base/net_errors.h" 26 #include "net/base/net_log.h" 27 #include "net/base/net_util.h" 28 #include "net/base/network_change_notifier.h" 29 #include "net/socket/socket_net_log_params.h" 30 31 // If we don't have a definition for TCPI_OPT_SYN_DATA, create one. 32 #ifndef TCPI_OPT_SYN_DATA 33 #define TCPI_OPT_SYN_DATA 32 34 #endif 35 36 namespace net { 37 38 namespace { 39 40 const int kInvalidSocket = -1; 41 const int kTCPKeepAliveSeconds = 45; 42 43 // SetTCPNoDelay turns on/off buffering in the kernel. By default, TCP sockets 44 // will wait up to 200ms for more data to complete a packet before transmitting. 45 // After calling this function, the kernel will not wait. See TCP_NODELAY in 46 // `man 7 tcp`. 47 bool SetTCPNoDelay(int fd, bool no_delay) { 48 int on = no_delay ? 1 : 0; 49 int error = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, 50 sizeof(on)); 51 return error == 0; 52 } 53 54 // SetTCPKeepAlive sets SO_KEEPALIVE. 55 bool SetTCPKeepAlive(int fd, bool enable, int delay) { 56 int on = enable ? 1 : 0; 57 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) { 58 PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd; 59 return false; 60 } 61 #if defined(OS_LINUX) || defined(OS_ANDROID) 62 // Set seconds until first TCP keep alive. 63 if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) { 64 PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd; 65 return false; 66 } 67 // Set seconds between TCP keep alives. 68 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &delay, sizeof(delay))) { 69 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; 70 return false; 71 } 72 #endif 73 return true; 74 } 75 76 // Sets socket parameters. Returns the OS error code (or 0 on 77 // success). 78 int SetupSocket(int socket) { 79 if (SetNonBlocking(socket)) 80 return errno; 81 82 // This mirrors the behaviour on Windows. See the comment in 83 // tcp_client_socket_win.cc after searching for "NODELAY". 84 SetTCPNoDelay(socket, true); // If SetTCPNoDelay fails, we don't care. 85 SetTCPKeepAlive(socket, true, kTCPKeepAliveSeconds); 86 87 return 0; 88 } 89 90 // Creates a new socket and sets default parameters for it. Returns 91 // the OS error code (or 0 on success). 92 int CreateSocket(int family, int* socket) { 93 *socket = ::socket(family, SOCK_STREAM, IPPROTO_TCP); 94 if (*socket == kInvalidSocket) 95 return errno; 96 int error = SetupSocket(*socket); 97 if (error) { 98 if (HANDLE_EINTR(close(*socket)) < 0) 99 PLOG(ERROR) << "close"; 100 *socket = kInvalidSocket; 101 return error; 102 } 103 return 0; 104 } 105 106 int MapConnectError(int os_error) { 107 switch (os_error) { 108 case EACCES: 109 return ERR_NETWORK_ACCESS_DENIED; 110 case ETIMEDOUT: 111 return ERR_CONNECTION_TIMED_OUT; 112 default: { 113 int net_error = MapSystemError(os_error); 114 if (net_error == ERR_FAILED) 115 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. 116 117 // Give a more specific error when the user is offline. 118 if (net_error == ERR_ADDRESS_UNREACHABLE && 119 NetworkChangeNotifier::IsOffline()) { 120 return ERR_INTERNET_DISCONNECTED; 121 } 122 return net_error; 123 } 124 } 125 } 126 127 } // namespace 128 129 //----------------------------------------------------------------------------- 130 131 TCPClientSocketLibevent::TCPClientSocketLibevent( 132 const AddressList& addresses, 133 net::NetLog* net_log, 134 const net::NetLog::Source& source) 135 : socket_(kInvalidSocket), 136 bound_socket_(kInvalidSocket), 137 addresses_(addresses), 138 current_address_index_(-1), 139 read_watcher_(this), 140 write_watcher_(this), 141 next_connect_state_(CONNECT_STATE_NONE), 142 connect_os_error_(0), 143 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), 144 previously_disconnected_(false), 145 use_tcp_fastopen_(IsTCPFastOpenEnabled()), 146 tcp_fastopen_connected_(false), 147 fast_open_status_(FAST_OPEN_STATUS_UNKNOWN) { 148 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 149 source.ToEventParametersCallback()); 150 } 151 152 TCPClientSocketLibevent::~TCPClientSocketLibevent() { 153 Disconnect(); 154 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 155 if (tcp_fastopen_connected_) { 156 UMA_HISTOGRAM_ENUMERATION("Net.TcpFastOpenSocketConnection", 157 fast_open_status_, FAST_OPEN_MAX_VALUE); 158 } 159 } 160 161 int TCPClientSocketLibevent::AdoptSocket(int socket) { 162 DCHECK_EQ(socket_, kInvalidSocket); 163 164 int error = SetupSocket(socket); 165 if (error) 166 return MapSystemError(error); 167 168 socket_ = socket; 169 170 // This is to make GetPeerAddress() work. It's up to the caller ensure 171 // that |address_| contains a reasonable address for this 172 // socket. (i.e. at least match IPv4 vs IPv6!). 173 current_address_index_ = 0; 174 use_history_.set_was_ever_connected(); 175 176 return OK; 177 } 178 179 int TCPClientSocketLibevent::Bind(const IPEndPoint& address) { 180 if (current_address_index_ >= 0 || bind_address_.get()) { 181 // Cannot bind the socket if we are already bound connected or 182 // connecting. 183 return ERR_UNEXPECTED; 184 } 185 186 SockaddrStorage storage; 187 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 188 return ERR_INVALID_ARGUMENT; 189 190 // Create |bound_socket_| and try to bind it to |address|. 191 int error = CreateSocket(address.GetSockAddrFamily(), &bound_socket_); 192 if (error) 193 return MapSystemError(error); 194 195 if (HANDLE_EINTR(bind(bound_socket_, storage.addr, storage.addr_len))) { 196 error = errno; 197 if (HANDLE_EINTR(close(bound_socket_)) < 0) 198 PLOG(ERROR) << "close"; 199 bound_socket_ = kInvalidSocket; 200 return MapSystemError(error); 201 } 202 203 bind_address_.reset(new IPEndPoint(address)); 204 205 return 0; 206 } 207 208 int TCPClientSocketLibevent::Connect(const CompletionCallback& callback) { 209 DCHECK(CalledOnValidThread()); 210 211 // If already connected, then just return OK. 212 if (socket_ != kInvalidSocket) 213 return OK; 214 215 base::StatsCounter connects("tcp.connect"); 216 connects.Increment(); 217 218 DCHECK(!waiting_connect()); 219 220 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 221 addresses_.CreateNetLogCallback()); 222 223 // We will try to connect to each address in addresses_. Start with the 224 // first one in the list. 225 next_connect_state_ = CONNECT_STATE_CONNECT; 226 current_address_index_ = 0; 227 228 int rv = DoConnectLoop(OK); 229 if (rv == ERR_IO_PENDING) { 230 // Synchronous operation not supported. 231 DCHECK(!callback.is_null()); 232 write_callback_ = callback; 233 } else { 234 LogConnectCompletion(rv); 235 } 236 237 return rv; 238 } 239 240 int TCPClientSocketLibevent::DoConnectLoop(int result) { 241 DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE); 242 243 int rv = result; 244 do { 245 ConnectState state = next_connect_state_; 246 next_connect_state_ = CONNECT_STATE_NONE; 247 switch (state) { 248 case CONNECT_STATE_CONNECT: 249 DCHECK_EQ(OK, rv); 250 rv = DoConnect(); 251 break; 252 case CONNECT_STATE_CONNECT_COMPLETE: 253 rv = DoConnectComplete(rv); 254 break; 255 default: 256 LOG(DFATAL) << "bad state"; 257 rv = ERR_UNEXPECTED; 258 break; 259 } 260 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); 261 262 return rv; 263 } 264 265 int TCPClientSocketLibevent::DoConnect() { 266 DCHECK_GE(current_address_index_, 0); 267 DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size())); 268 DCHECK_EQ(0, connect_os_error_); 269 270 const IPEndPoint& endpoint = addresses_[current_address_index_]; 271 272 if (previously_disconnected_) { 273 use_history_.Reset(); 274 previously_disconnected_ = false; 275 } 276 277 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 278 CreateNetLogIPEndPointCallback(&endpoint)); 279 280 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; 281 282 if (bound_socket_ != kInvalidSocket) { 283 DCHECK(bind_address_.get()); 284 socket_ = bound_socket_; 285 bound_socket_ = kInvalidSocket; 286 } else { 287 // Create a non-blocking socket. 288 connect_os_error_ = CreateSocket(endpoint.GetSockAddrFamily(), &socket_); 289 if (connect_os_error_) 290 return MapSystemError(connect_os_error_); 291 292 if (bind_address_.get()) { 293 SockaddrStorage storage; 294 if (!bind_address_->ToSockAddr(storage.addr, &storage.addr_len)) 295 return ERR_INVALID_ARGUMENT; 296 if (HANDLE_EINTR(bind(socket_, storage.addr, storage.addr_len))) 297 return MapSystemError(errno); 298 } 299 } 300 301 // Connect the socket. 302 if (!use_tcp_fastopen_) { 303 SockaddrStorage storage; 304 if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len)) 305 return ERR_INVALID_ARGUMENT; 306 307 if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) { 308 // Connected without waiting! 309 return OK; 310 } 311 } else { 312 // With TCP FastOpen, we pretend that the socket is connected. 313 DCHECK(!tcp_fastopen_connected_); 314 return OK; 315 } 316 317 // Check if the connect() failed synchronously. 318 connect_os_error_ = errno; 319 if (connect_os_error_ != EINPROGRESS) 320 return MapConnectError(connect_os_error_); 321 322 // Otherwise the connect() is going to complete asynchronously, so watch 323 // for its completion. 324 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 325 socket_, true, base::MessageLoopForIO::WATCH_WRITE, 326 &write_socket_watcher_, &write_watcher_)) { 327 connect_os_error_ = errno; 328 DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_; 329 return MapSystemError(connect_os_error_); 330 } 331 332 return ERR_IO_PENDING; 333 } 334 335 int TCPClientSocketLibevent::DoConnectComplete(int result) { 336 // Log the end of this attempt (and any OS error it threw). 337 int os_error = connect_os_error_; 338 connect_os_error_ = 0; 339 if (result != OK) { 340 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 341 NetLog::IntegerCallback("os_error", os_error)); 342 } else { 343 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT); 344 } 345 346 if (result == OK) { 347 write_socket_watcher_.StopWatchingFileDescriptor(); 348 use_history_.set_was_ever_connected(); 349 return OK; // Done! 350 } 351 352 // Close whatever partially connected socket we currently have. 353 DoDisconnect(); 354 355 // Try to fall back to the next address in the list. 356 if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) { 357 next_connect_state_ = CONNECT_STATE_CONNECT; 358 ++current_address_index_; 359 return OK; 360 } 361 362 // Otherwise there is nothing to fall back to, so give up. 363 return result; 364 } 365 366 void TCPClientSocketLibevent::Disconnect() { 367 DCHECK(CalledOnValidThread()); 368 369 DoDisconnect(); 370 current_address_index_ = -1; 371 bind_address_.reset(); 372 } 373 374 void TCPClientSocketLibevent::DoDisconnect() { 375 if (socket_ == kInvalidSocket) 376 return; 377 378 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 379 DCHECK(ok); 380 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 381 DCHECK(ok); 382 if (HANDLE_EINTR(close(socket_)) < 0) 383 PLOG(ERROR) << "close"; 384 socket_ = kInvalidSocket; 385 previously_disconnected_ = true; 386 } 387 388 bool TCPClientSocketLibevent::IsConnected() const { 389 DCHECK(CalledOnValidThread()); 390 391 if (socket_ == kInvalidSocket || waiting_connect()) 392 return false; 393 394 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { 395 // With TCP FastOpen, we pretend that the socket is connected. 396 // This allows GetPeerAddress() to return current_ai_ as the peer 397 // address. Since we don't fail over to the next address if 398 // sendto() fails, current_ai_ is the only possible peer address. 399 CHECK_LT(current_address_index_, static_cast<int>(addresses_.size())); 400 return true; 401 } 402 403 // Check if connection is alive. 404 char c; 405 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 406 if (rv == 0) 407 return false; 408 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) 409 return false; 410 411 return true; 412 } 413 414 bool TCPClientSocketLibevent::IsConnectedAndIdle() const { 415 DCHECK(CalledOnValidThread()); 416 417 if (socket_ == kInvalidSocket || waiting_connect()) 418 return false; 419 420 // TODO(wtc): should we also handle the TCP FastOpen case here, 421 // as we do in IsConnected()? 422 423 // Check if connection is alive and we haven't received any data 424 // unexpectedly. 425 char c; 426 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 427 if (rv >= 0) 428 return false; 429 if (errno != EAGAIN && errno != EWOULDBLOCK) 430 return false; 431 432 return true; 433 } 434 435 int TCPClientSocketLibevent::Read(IOBuffer* buf, 436 int buf_len, 437 const CompletionCallback& callback) { 438 DCHECK(CalledOnValidThread()); 439 DCHECK_NE(kInvalidSocket, socket_); 440 DCHECK(!waiting_connect()); 441 DCHECK(read_callback_.is_null()); 442 // Synchronous operation not supported 443 DCHECK(!callback.is_null()); 444 DCHECK_GT(buf_len, 0); 445 446 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); 447 if (nread >= 0) { 448 base::StatsCounter read_bytes("tcp.read_bytes"); 449 read_bytes.Add(nread); 450 if (nread > 0) 451 use_history_.set_was_used_to_convey_data(); 452 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, 453 buf->data()); 454 RecordFastOpenStatus(); 455 return nread; 456 } 457 if (errno != EAGAIN && errno != EWOULDBLOCK) { 458 int net_error = MapSystemError(errno); 459 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 460 CreateNetLogSocketErrorCallback(net_error, errno)); 461 return net_error; 462 } 463 464 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 465 socket_, true, base::MessageLoopForIO::WATCH_READ, 466 &read_socket_watcher_, &read_watcher_)) { 467 DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno; 468 return MapSystemError(errno); 469 } 470 471 read_buf_ = buf; 472 read_buf_len_ = buf_len; 473 read_callback_ = callback; 474 return ERR_IO_PENDING; 475 } 476 477 int TCPClientSocketLibevent::Write(IOBuffer* buf, 478 int buf_len, 479 const CompletionCallback& callback) { 480 DCHECK(CalledOnValidThread()); 481 DCHECK_NE(kInvalidSocket, socket_); 482 DCHECK(!waiting_connect()); 483 DCHECK(write_callback_.is_null()); 484 // Synchronous operation not supported 485 DCHECK(!callback.is_null()); 486 DCHECK_GT(buf_len, 0); 487 488 int nwrite = InternalWrite(buf, buf_len); 489 if (nwrite >= 0) { 490 base::StatsCounter write_bytes("tcp.write_bytes"); 491 write_bytes.Add(nwrite); 492 if (nwrite > 0) 493 use_history_.set_was_used_to_convey_data(); 494 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, 495 buf->data()); 496 return nwrite; 497 } 498 if (errno != EAGAIN && errno != EWOULDBLOCK) { 499 int net_error = MapSystemError(errno); 500 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 501 CreateNetLogSocketErrorCallback(net_error, errno)); 502 return net_error; 503 } 504 505 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( 506 socket_, true, base::MessageLoopForIO::WATCH_WRITE, 507 &write_socket_watcher_, &write_watcher_)) { 508 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; 509 return MapSystemError(errno); 510 } 511 512 write_buf_ = buf; 513 write_buf_len_ = buf_len; 514 write_callback_ = callback; 515 return ERR_IO_PENDING; 516 } 517 518 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { 519 int nwrite; 520 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { 521 SockaddrStorage storage; 522 if (!addresses_[current_address_index_].ToSockAddr(storage.addr, 523 &storage.addr_len)) { 524 errno = EINVAL; 525 return -1; 526 } 527 528 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN. 529 #if defined(OS_LINUX) 530 // sendto() will fail with EPIPE when the system doesn't support TCP Fast 531 // Open. Theoretically that shouldn't happen since the caller should check 532 // for system support on startup, but users may dynamically disable TCP Fast 533 // Open via sysctl. 534 flags |= MSG_NOSIGNAL; 535 #endif // defined(OS_LINUX) 536 nwrite = HANDLE_EINTR(sendto(socket_, 537 buf->data(), 538 buf_len, 539 flags, 540 storage.addr, 541 storage.addr_len)); 542 tcp_fastopen_connected_ = true; 543 544 if (nwrite < 0) { 545 DCHECK_NE(EPIPE, errno); 546 547 // If errno == EINPROGRESS, that means the kernel didn't have a cookie 548 // and would block. The kernel is internally doing a connect() though. 549 // Remap EINPROGRESS to EAGAIN so we treat this the same as our other 550 // asynchronous cases. Note that the user buffer has not been copied to 551 // kernel space. 552 if (errno == EINPROGRESS) { 553 errno = EAGAIN; 554 fast_open_status_ = FAST_OPEN_SLOW_CONNECT_RETURN; 555 } else { 556 fast_open_status_ = FAST_OPEN_ERROR; 557 } 558 } else { 559 fast_open_status_ = FAST_OPEN_FAST_CONNECT_RETURN; 560 } 561 } else { 562 nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); 563 } 564 return nwrite; 565 } 566 567 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { 568 DCHECK(CalledOnValidThread()); 569 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 570 reinterpret_cast<const char*>(&size), 571 sizeof(size)); 572 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 573 return rv == 0; 574 } 575 576 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { 577 DCHECK(CalledOnValidThread()); 578 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 579 reinterpret_cast<const char*>(&size), 580 sizeof(size)); 581 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 582 return rv == 0; 583 } 584 585 bool TCPClientSocketLibevent::SetKeepAlive(bool enable, int delay) { 586 int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_; 587 return SetTCPKeepAlive(socket, enable, delay); 588 } 589 590 bool TCPClientSocketLibevent::SetNoDelay(bool no_delay) { 591 int socket = socket_ != kInvalidSocket ? socket_ : bound_socket_; 592 return SetTCPNoDelay(socket, no_delay); 593 } 594 595 void TCPClientSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { 596 socket_->RecordFastOpenStatus(); 597 if (!socket_->read_callback_.is_null()) 598 socket_->DidCompleteRead(); 599 } 600 601 void TCPClientSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) { 602 if (socket_->waiting_connect()) { 603 socket_->DidCompleteConnect(); 604 } else if (!socket_->write_callback_.is_null()) { 605 socket_->DidCompleteWrite(); 606 } 607 } 608 609 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { 610 if (net_error == OK) 611 UpdateConnectionTypeHistograms(CONNECTION_ANY); 612 613 if (net_error != OK) { 614 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 615 return; 616 } 617 618 SockaddrStorage storage; 619 int rv = getsockname(socket_, storage.addr, &storage.addr_len); 620 if (rv != 0) { 621 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; 622 NOTREACHED(); 623 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 624 return; 625 } 626 627 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 628 CreateNetLogSourceAddressCallback(storage.addr, 629 storage.addr_len)); 630 } 631 632 void TCPClientSocketLibevent::DoReadCallback(int rv) { 633 DCHECK_NE(rv, ERR_IO_PENDING); 634 DCHECK(!read_callback_.is_null()); 635 636 // since Run may result in Read being called, clear read_callback_ up front. 637 CompletionCallback c = read_callback_; 638 read_callback_.Reset(); 639 c.Run(rv); 640 } 641 642 void TCPClientSocketLibevent::DoWriteCallback(int rv) { 643 DCHECK_NE(rv, ERR_IO_PENDING); 644 DCHECK(!write_callback_.is_null()); 645 646 // since Run may result in Write being called, clear write_callback_ up front. 647 CompletionCallback c = write_callback_; 648 write_callback_.Reset(); 649 c.Run(rv); 650 } 651 652 void TCPClientSocketLibevent::DidCompleteConnect() { 653 DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE); 654 655 // Get the error that connect() completed with. 656 int os_error = 0; 657 socklen_t len = sizeof(os_error); 658 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0) 659 os_error = errno; 660 661 // TODO(eroman): Is this check really necessary? 662 if (os_error == EINPROGRESS || os_error == EALREADY) { 663 NOTREACHED(); // This indicates a bug in libevent or our code. 664 return; 665 } 666 667 connect_os_error_ = os_error; 668 int rv = DoConnectLoop(MapConnectError(os_error)); 669 if (rv != ERR_IO_PENDING) { 670 LogConnectCompletion(rv); 671 DoWriteCallback(rv); 672 } 673 } 674 675 void TCPClientSocketLibevent::DidCompleteRead() { 676 int bytes_transferred; 677 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), 678 read_buf_len_)); 679 680 int result; 681 if (bytes_transferred >= 0) { 682 result = bytes_transferred; 683 base::StatsCounter read_bytes("tcp.read_bytes"); 684 read_bytes.Add(bytes_transferred); 685 if (bytes_transferred > 0) 686 use_history_.set_was_used_to_convey_data(); 687 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, result, 688 read_buf_->data()); 689 } else { 690 result = MapSystemError(errno); 691 if (result != ERR_IO_PENDING) { 692 net_log_.AddEvent(NetLog::TYPE_SOCKET_READ_ERROR, 693 CreateNetLogSocketErrorCallback(result, errno)); 694 } 695 } 696 697 if (result != ERR_IO_PENDING) { 698 read_buf_ = NULL; 699 read_buf_len_ = 0; 700 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 701 DCHECK(ok); 702 DoReadCallback(result); 703 } 704 } 705 706 void TCPClientSocketLibevent::DidCompleteWrite() { 707 int bytes_transferred; 708 bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), 709 write_buf_len_)); 710 711 int result; 712 if (bytes_transferred >= 0) { 713 result = bytes_transferred; 714 base::StatsCounter write_bytes("tcp.write_bytes"); 715 write_bytes.Add(bytes_transferred); 716 if (bytes_transferred > 0) 717 use_history_.set_was_used_to_convey_data(); 718 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, result, 719 write_buf_->data()); 720 } else { 721 result = MapSystemError(errno); 722 if (result != ERR_IO_PENDING) { 723 net_log_.AddEvent(NetLog::TYPE_SOCKET_WRITE_ERROR, 724 CreateNetLogSocketErrorCallback(result, errno)); 725 } 726 } 727 728 if (result != ERR_IO_PENDING) { 729 write_buf_ = NULL; 730 write_buf_len_ = 0; 731 write_socket_watcher_.StopWatchingFileDescriptor(); 732 DoWriteCallback(result); 733 } 734 } 735 736 int TCPClientSocketLibevent::GetPeerAddress(IPEndPoint* address) const { 737 DCHECK(CalledOnValidThread()); 738 DCHECK(address); 739 if (!IsConnected()) 740 return ERR_SOCKET_NOT_CONNECTED; 741 *address = addresses_[current_address_index_]; 742 return OK; 743 } 744 745 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 746 DCHECK(CalledOnValidThread()); 747 DCHECK(address); 748 if (socket_ == kInvalidSocket) { 749 if (bind_address_.get()) { 750 *address = *bind_address_; 751 return OK; 752 } 753 return ERR_SOCKET_NOT_CONNECTED; 754 } 755 756 SockaddrStorage storage; 757 if (getsockname(socket_, storage.addr, &storage.addr_len)) 758 return MapSystemError(errno); 759 if (!address->FromSockAddr(storage.addr, storage.addr_len)) 760 return ERR_FAILED; 761 762 return OK; 763 } 764 765 void TCPClientSocketLibevent::RecordFastOpenStatus() { 766 if (use_tcp_fastopen_ && 767 (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN || 768 fast_open_status_ == FAST_OPEN_SLOW_CONNECT_RETURN)) { 769 DCHECK_NE(FAST_OPEN_STATUS_UNKNOWN, fast_open_status_); 770 bool getsockopt_success(false); 771 bool server_acked_data(false); 772 #if defined(TCP_INFO) 773 // Probe to see the if the socket used TCP Fast Open. 774 tcp_info info; 775 socklen_t info_len = sizeof(tcp_info); 776 getsockopt_success = 777 getsockopt(socket_, IPPROTO_TCP, TCP_INFO, &info, &info_len) == 0 && 778 info_len == sizeof(tcp_info); 779 server_acked_data = getsockopt_success && 780 (info.tcpi_options & TCPI_OPT_SYN_DATA); 781 #endif 782 if (getsockopt_success) { 783 if (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN) { 784 fast_open_status_ = (server_acked_data ? FAST_OPEN_SYN_DATA_ACK : 785 FAST_OPEN_SYN_DATA_NACK); 786 } else { 787 fast_open_status_ = (server_acked_data ? FAST_OPEN_NO_SYN_DATA_ACK : 788 FAST_OPEN_NO_SYN_DATA_NACK); 789 } 790 } else { 791 fast_open_status_ = (fast_open_status_ == FAST_OPEN_FAST_CONNECT_RETURN ? 792 FAST_OPEN_SYN_DATA_FAILED : 793 FAST_OPEN_NO_SYN_DATA_FAILED); 794 } 795 } 796 } 797 798 const BoundNetLog& TCPClientSocketLibevent::NetLog() const { 799 return net_log_; 800 } 801 802 void TCPClientSocketLibevent::SetSubresourceSpeculation() { 803 use_history_.set_subresource_speculation(); 804 } 805 806 void TCPClientSocketLibevent::SetOmniboxSpeculation() { 807 use_history_.set_omnibox_speculation(); 808 } 809 810 bool TCPClientSocketLibevent::WasEverUsed() const { 811 return use_history_.was_used_to_convey_data(); 812 } 813 814 bool TCPClientSocketLibevent::UsingTCPFastOpen() const { 815 return use_tcp_fastopen_; 816 } 817 818 bool TCPClientSocketLibevent::WasNpnNegotiated() const { 819 return false; 820 } 821 822 NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const { 823 return kProtoUnknown; 824 } 825 826 bool TCPClientSocketLibevent::GetSSLInfo(SSLInfo* ssl_info) { 827 return false; 828 } 829 830 } // namespace net 831