1 // Copyright (c) 2010 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/eintr_wrapper.h" 17 #include "base/logging.h" 18 #include "base/message_loop.h" 19 #include "base/metrics/stats_counters.h" 20 #include "base/string_util.h" 21 #include "net/base/address_list_net_log_param.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 #if defined(USE_SYSTEM_LIBEVENT) 30 #include <event.h> 31 #else 32 #include "third_party/libevent/event.h" 33 #endif 34 #ifdef ANDROID 35 #include <cutils/qtaguid.h> 36 #endif 37 38 namespace net { 39 40 namespace { 41 42 const int kInvalidSocket = -1; 43 44 // DisableNagle turns off buffering in the kernel. By default, TCP sockets will 45 // wait up to 200ms for more data to complete a packet before transmitting. 46 // After calling this function, the kernel will not wait. See TCP_NODELAY in 47 // `man 7 tcp`. 48 int DisableNagle(int fd) { 49 int on = 1; 50 return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); 51 } 52 53 // SetTCPKeepAlive sets SO_KEEPALIVE. 54 void SetTCPKeepAlive(int fd) { 55 int optval = 1; 56 socklen_t optlen = sizeof(optval); 57 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) { 58 PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd; 59 return; 60 } 61 #if defined(OS_LINUX) 62 // Set seconds until first TCP keep alive. 63 #ifdef ANDROID 64 optval = 25; 65 #else 66 optval = 45; 67 #endif 68 if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen)) { 69 PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd; 70 return; 71 } 72 // Set seconds between TCP keep alives. 73 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen)) { 74 PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; 75 return; 76 } 77 #endif 78 } 79 80 int MapConnectError(int os_error) { 81 switch (os_error) { 82 case EACCES: 83 return ERR_NETWORK_ACCESS_DENIED; 84 case ETIMEDOUT: 85 return ERR_CONNECTION_TIMED_OUT; 86 default: { 87 int net_error = MapSystemError(os_error); 88 if (net_error == ERR_FAILED) 89 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. 90 91 // Give a more specific error when the user is offline. 92 if (net_error == ERR_ADDRESS_UNREACHABLE && 93 NetworkChangeNotifier::IsOffline()) { 94 return ERR_INTERNET_DISCONNECTED; 95 } 96 return net_error; 97 } 98 } 99 } 100 101 } // namespace 102 103 //----------------------------------------------------------------------------- 104 105 TCPClientSocketLibevent::TCPClientSocketLibevent( 106 const AddressList& addresses, 107 net::NetLog* net_log, 108 const net::NetLog::Source& source) 109 : socket_(kInvalidSocket), 110 addresses_(addresses), 111 current_ai_(NULL), 112 read_watcher_(this), 113 write_watcher_(this), 114 read_callback_(NULL), 115 write_callback_(NULL), 116 next_connect_state_(CONNECT_STATE_NONE), 117 connect_os_error_(0), 118 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), 119 previously_disconnected_(false), 120 use_tcp_fastopen_(false), 121 tcp_fastopen_connected_(false) 122 #ifdef ANDROID 123 , wait_for_connect_(false) 124 , valid_uid_(false) 125 , calling_uid_(0) 126 #endif 127 { 128 scoped_refptr<NetLog::EventParameters> params; 129 if (source.is_valid()) 130 params = new NetLogSourceParameter("source_dependency", source); 131 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); 132 133 if (is_tcp_fastopen_enabled()) 134 use_tcp_fastopen_ = true; 135 } 136 137 TCPClientSocketLibevent::~TCPClientSocketLibevent() { 138 Disconnect(); 139 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); 140 } 141 142 void TCPClientSocketLibevent::AdoptSocket(int socket) { 143 DCHECK_EQ(socket_, kInvalidSocket); 144 socket_ = socket; 145 int error = SetupSocket(); 146 DCHECK_EQ(0, error); 147 // This is to make GetPeerAddress work. It's up to the test that is calling 148 // this function to ensure that address_ contains a reasonable address for 149 // this socket. (i.e. at least match IPv4 vs IPv6!). 150 current_ai_ = addresses_.head(); 151 use_history_.set_was_ever_connected(); 152 } 153 154 int TCPClientSocketLibevent::Connect(CompletionCallback* callback 155 #ifdef ANDROID 156 , bool wait_for_connect 157 , bool valid_uid 158 , uid_t calling_uid 159 #endif 160 ) { 161 #ifdef ANDROID 162 wait_for_connect_ = wait_for_connect; 163 valid_uid_ = valid_uid; 164 calling_uid_ = calling_uid; 165 #endif 166 DCHECK(CalledOnValidThread()); 167 168 // If already connected, then just return OK. 169 if (socket_ != kInvalidSocket) 170 return OK; 171 172 base::StatsCounter connects("tcp.connect"); 173 connects.Increment(); 174 175 DCHECK(!waiting_connect()); 176 177 net_log_.BeginEvent( 178 NetLog::TYPE_TCP_CONNECT, 179 make_scoped_refptr(new AddressListNetLogParam(addresses_))); 180 181 // We will try to connect to each address in addresses_. Start with the 182 // first one in the list. 183 next_connect_state_ = CONNECT_STATE_CONNECT; 184 current_ai_ = addresses_.head(); 185 186 int rv = DoConnectLoop(OK); 187 if (rv == ERR_IO_PENDING) { 188 // Synchronous operation not supported. 189 DCHECK(callback); 190 write_callback_ = callback; 191 } else { 192 LogConnectCompletion(rv); 193 } 194 195 return rv; 196 } 197 198 int TCPClientSocketLibevent::DoConnectLoop(int result) { 199 DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE); 200 201 int rv = result; 202 do { 203 ConnectState state = next_connect_state_; 204 next_connect_state_ = CONNECT_STATE_NONE; 205 switch (state) { 206 case CONNECT_STATE_CONNECT: 207 DCHECK_EQ(OK, rv); 208 rv = DoConnect(); 209 break; 210 case CONNECT_STATE_CONNECT_COMPLETE: 211 rv = DoConnectComplete(rv); 212 break; 213 default: 214 LOG(DFATAL) << "bad state"; 215 rv = ERR_UNEXPECTED; 216 break; 217 } 218 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); 219 220 return rv; 221 } 222 223 int TCPClientSocketLibevent::DoConnect() { 224 DCHECK(current_ai_); 225 226 DCHECK_EQ(0, connect_os_error_); 227 228 if (previously_disconnected_) { 229 use_history_.Reset(); 230 previously_disconnected_ = false; 231 } 232 233 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 234 make_scoped_refptr(new NetLogStringParameter( 235 "address", NetAddressToStringWithPort(current_ai_)))); 236 237 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; 238 239 // Create a non-blocking socket. 240 connect_os_error_ = CreateSocket(current_ai_); 241 if (connect_os_error_) 242 return MapSystemError(connect_os_error_); 243 244 // Connect the socket. 245 if (!use_tcp_fastopen_) { 246 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr, 247 static_cast<int>(current_ai_->ai_addrlen)))) { 248 // Connected without waiting! 249 return OK; 250 #ifdef ANDROID 251 } else if (errno == EINPROGRESS && wait_for_connect_) { 252 fd_set writeset; 253 FD_ZERO(&writeset); 254 FD_SET(socket_, &writeset); 255 timeval tv; 256 tv.tv_sec = 20; 257 tv.tv_usec = 0; 258 int res = HANDLE_EINTR(select(socket_ + 1, 0, &writeset, 0, &tv)); 259 if (res > 0) 260 return OK; 261 return MapConnectError(ETIMEDOUT); 262 #endif 263 } 264 } else { 265 // With TCP FastOpen, we pretend that the socket is connected. 266 DCHECK(!tcp_fastopen_connected_); 267 return OK; 268 } 269 270 // Check if the connect() failed synchronously. 271 connect_os_error_ = errno; 272 if (connect_os_error_ != EINPROGRESS) 273 return MapConnectError(connect_os_error_); 274 275 // Otherwise the connect() is going to complete asynchronously, so watch 276 // for its completion. 277 if (!MessageLoopForIO::current()->WatchFileDescriptor( 278 socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_, 279 &write_watcher_)) { 280 connect_os_error_ = errno; 281 DVLOG(1) << "WatchFileDescriptor failed: " << connect_os_error_; 282 return MapSystemError(connect_os_error_); 283 } 284 285 return ERR_IO_PENDING; 286 } 287 288 int TCPClientSocketLibevent::DoConnectComplete(int result) { 289 // Log the end of this attempt (and any OS error it threw). 290 int os_error = connect_os_error_; 291 connect_os_error_ = 0; 292 scoped_refptr<NetLog::EventParameters> params; 293 if (result != OK) 294 params = new NetLogIntegerParameter("os_error", os_error); 295 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, params); 296 297 write_socket_watcher_.StopWatchingFileDescriptor(); 298 299 if (result == OK) { 300 use_history_.set_was_ever_connected(); 301 return OK; // Done! 302 } 303 304 // Close whatever partially connected socket we currently have. 305 DoDisconnect(); 306 307 // Try to fall back to the next address in the list. 308 if (current_ai_->ai_next) { 309 next_connect_state_ = CONNECT_STATE_CONNECT; 310 current_ai_ = current_ai_->ai_next; 311 return OK; 312 } 313 314 // Otherwise there is nothing to fall back to, so give up. 315 return result; 316 } 317 318 void TCPClientSocketLibevent::Disconnect() { 319 DCHECK(CalledOnValidThread()); 320 321 DoDisconnect(); 322 current_ai_ = NULL; 323 } 324 325 void TCPClientSocketLibevent::DoDisconnect() { 326 if (socket_ == kInvalidSocket) 327 return; 328 329 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 330 DCHECK(ok); 331 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 332 DCHECK(ok); 333 334 #ifdef ANDROID 335 if (valid_uid_) 336 qtaguid_untagSocket(socket_); 337 #endif 338 339 if (HANDLE_EINTR(close(socket_)) < 0) 340 PLOG(ERROR) << "close"; 341 socket_ = kInvalidSocket; 342 previously_disconnected_ = true; 343 } 344 345 bool TCPClientSocketLibevent::IsConnected() const { 346 DCHECK(CalledOnValidThread()); 347 348 if (socket_ == kInvalidSocket || waiting_connect()) 349 return false; 350 351 // Check if connection is alive. 352 char c; 353 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 354 if (rv == 0) 355 return false; 356 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) 357 return false; 358 359 return true; 360 } 361 362 bool TCPClientSocketLibevent::IsConnectedAndIdle() const { 363 DCHECK(CalledOnValidThread()); 364 365 if (socket_ == kInvalidSocket || waiting_connect()) 366 return false; 367 368 // Check if connection is alive and we haven't received any data 369 // unexpectedly. 370 char c; 371 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 372 if (rv >= 0) 373 return false; 374 if (errno != EAGAIN && errno != EWOULDBLOCK) 375 return false; 376 377 return true; 378 } 379 380 int TCPClientSocketLibevent::Read(IOBuffer* buf, 381 int buf_len, 382 CompletionCallback* callback) { 383 DCHECK(CalledOnValidThread()); 384 DCHECK_NE(kInvalidSocket, socket_); 385 DCHECK(!waiting_connect()); 386 DCHECK(!read_callback_); 387 // Synchronous operation not supported 388 DCHECK(callback); 389 DCHECK_GT(buf_len, 0); 390 391 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); 392 if (nread >= 0) { 393 base::StatsCounter read_bytes("tcp.read_bytes"); 394 read_bytes.Add(nread); 395 if (nread > 0) 396 use_history_.set_was_used_to_convey_data(); 397 LogByteTransfer( 398 net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, nread, buf->data()); 399 return nread; 400 } 401 if (errno != EAGAIN && errno != EWOULDBLOCK) { 402 DVLOG(1) << "read failed, errno " << errno; 403 return MapSystemError(errno); 404 } 405 406 if (!MessageLoopForIO::current()->WatchFileDescriptor( 407 socket_, true, MessageLoopForIO::WATCH_READ, 408 &read_socket_watcher_, &read_watcher_)) { 409 DVLOG(1) << "WatchFileDescriptor failed on read, errno " << errno; 410 return MapSystemError(errno); 411 } 412 413 read_buf_ = buf; 414 read_buf_len_ = buf_len; 415 read_callback_ = callback; 416 return ERR_IO_PENDING; 417 } 418 419 int TCPClientSocketLibevent::Write(IOBuffer* buf, 420 int buf_len, 421 CompletionCallback* callback) { 422 DCHECK(CalledOnValidThread()); 423 DCHECK_NE(kInvalidSocket, socket_); 424 DCHECK(!waiting_connect()); 425 DCHECK(!write_callback_); 426 // Synchronous operation not supported 427 DCHECK(callback); 428 DCHECK_GT(buf_len, 0); 429 430 int nwrite = InternalWrite(buf, buf_len); 431 if (nwrite >= 0) { 432 base::StatsCounter write_bytes("tcp.write_bytes"); 433 write_bytes.Add(nwrite); 434 if (nwrite > 0) 435 use_history_.set_was_used_to_convey_data(); 436 LogByteTransfer( 437 net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data()); 438 return nwrite; 439 } 440 if (errno != EAGAIN && errno != EWOULDBLOCK) 441 return MapSystemError(errno); 442 443 if (!MessageLoopForIO::current()->WatchFileDescriptor( 444 socket_, true, MessageLoopForIO::WATCH_WRITE, 445 &write_socket_watcher_, &write_watcher_)) { 446 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; 447 return MapSystemError(errno); 448 } 449 450 write_buf_ = buf; 451 write_buf_len_ = buf_len; 452 write_callback_ = callback; 453 return ERR_IO_PENDING; 454 } 455 456 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { 457 int nwrite; 458 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { 459 // We have a limited amount of data to send in the SYN packet. 460 int kMaxFastOpenSendLength = 1420; 461 462 buf_len = std::min(kMaxFastOpenSendLength, buf_len); 463 464 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN 465 nwrite = HANDLE_EINTR(sendto(socket_, 466 buf->data(), 467 buf_len, 468 flags, 469 current_ai_->ai_addr, 470 static_cast<int>(current_ai_->ai_addrlen))); 471 tcp_fastopen_connected_ = true; 472 473 if (nwrite < 0) { 474 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN. 475 if (errno == EINPROGRESS) 476 errno = EAGAIN; 477 478 // Unlike "normal" nonblocking sockets, the data is already queued, 479 // so tell the app that we've consumed it. 480 return buf_len; 481 } 482 } else { 483 nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); 484 } 485 return nwrite; 486 } 487 488 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { 489 DCHECK(CalledOnValidThread()); 490 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 491 reinterpret_cast<const char*>(&size), 492 sizeof(size)); 493 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 494 return rv == 0; 495 } 496 497 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { 498 DCHECK(CalledOnValidThread()); 499 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 500 reinterpret_cast<const char*>(&size), 501 sizeof(size)); 502 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 503 return rv == 0; 504 } 505 506 507 int TCPClientSocketLibevent::CreateSocket(const addrinfo* ai) { 508 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 509 if (socket_ == kInvalidSocket) 510 return errno; 511 return SetupSocket(); 512 } 513 514 int TCPClientSocketLibevent::SetupSocket() { 515 if (SetNonBlocking(socket_)) { 516 const int err = errno; 517 518 #ifdef ANDROID 519 if (valid_uid_) 520 qtaguid_untagSocket(socket_); 521 #endif 522 523 close(socket_); 524 socket_ = kInvalidSocket; 525 return err; 526 } 527 528 // This mirrors the behaviour on Windows. See the comment in 529 // tcp_client_socket_win.cc after searching for "NODELAY". 530 DisableNagle(socket_); // If DisableNagle fails, we don't care. 531 532 // ANDROID: Disable TCP keep-alive for bug 5226268 533 // [Browser] http keep-alive packets are sent too frequently to network 534 #ifndef ANDROID 535 SetTCPKeepAlive(socket_); 536 #endif 537 538 #ifdef ANDROID 539 if (valid_uid_) 540 qtaguid_tagSocket(socket_, geteuid(), calling_uid_); 541 #endif 542 543 return 0; 544 } 545 546 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { 547 if (net_error == OK) 548 UpdateConnectionTypeHistograms(CONNECTION_ANY); 549 550 if (net_error != OK) { 551 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); 552 return; 553 } 554 555 struct sockaddr_storage source_address; 556 socklen_t addrlen = sizeof(source_address); 557 int rv = getsockname( 558 socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen); 559 if (rv != 0) { 560 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; 561 NOTREACHED(); 562 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); 563 return; 564 } 565 566 const std::string source_address_str = 567 NetAddressToStringWithPort( 568 reinterpret_cast<const struct sockaddr*>(&source_address), 569 sizeof(source_address)); 570 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, 571 make_scoped_refptr(new NetLogStringParameter( 572 "source address", 573 source_address_str))); 574 } 575 576 void TCPClientSocketLibevent::DoReadCallback(int rv) { 577 DCHECK_NE(rv, ERR_IO_PENDING); 578 DCHECK(read_callback_); 579 580 // since Run may result in Read being called, clear read_callback_ up front. 581 CompletionCallback* c = read_callback_; 582 read_callback_ = NULL; 583 c->Run(rv); 584 } 585 586 void TCPClientSocketLibevent::DoWriteCallback(int rv) { 587 DCHECK_NE(rv, ERR_IO_PENDING); 588 DCHECK(write_callback_); 589 590 // since Run may result in Write being called, clear write_callback_ up front. 591 CompletionCallback* c = write_callback_; 592 write_callback_ = NULL; 593 c->Run(rv); 594 } 595 596 void TCPClientSocketLibevent::DidCompleteConnect() { 597 DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE); 598 599 // Get the error that connect() completed with. 600 int os_error = 0; 601 socklen_t len = sizeof(os_error); 602 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0) 603 os_error = errno; 604 605 // TODO(eroman): Is this check really necessary? 606 if (os_error == EINPROGRESS || os_error == EALREADY) { 607 NOTREACHED(); // This indicates a bug in libevent or our code. 608 return; 609 } 610 611 connect_os_error_ = os_error; 612 int rv = DoConnectLoop(MapConnectError(os_error)); 613 if (rv != ERR_IO_PENDING) { 614 LogConnectCompletion(rv); 615 DoWriteCallback(rv); 616 } 617 } 618 619 void TCPClientSocketLibevent::DidCompleteRead() { 620 int bytes_transferred; 621 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), 622 read_buf_len_)); 623 624 int result; 625 if (bytes_transferred >= 0) { 626 result = bytes_transferred; 627 base::StatsCounter read_bytes("tcp.read_bytes"); 628 read_bytes.Add(bytes_transferred); 629 if (bytes_transferred > 0) 630 use_history_.set_was_used_to_convey_data(); 631 LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_RECEIVED, result, 632 read_buf_->data()); 633 } else { 634 result = MapSystemError(errno); 635 } 636 637 if (result != ERR_IO_PENDING) { 638 read_buf_ = NULL; 639 read_buf_len_ = 0; 640 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 641 DCHECK(ok); 642 DoReadCallback(result); 643 } 644 } 645 646 void TCPClientSocketLibevent::DidCompleteWrite() { 647 int bytes_transferred; 648 bytes_transferred = HANDLE_EINTR(write(socket_, write_buf_->data(), 649 write_buf_len_)); 650 651 int result; 652 if (bytes_transferred >= 0) { 653 result = bytes_transferred; 654 base::StatsCounter write_bytes("tcp.write_bytes"); 655 write_bytes.Add(bytes_transferred); 656 if (bytes_transferred > 0) 657 use_history_.set_was_used_to_convey_data(); 658 LogByteTransfer(net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, result, 659 write_buf_->data()); 660 } else { 661 result = MapSystemError(errno); 662 } 663 664 if (result != ERR_IO_PENDING) { 665 write_buf_ = NULL; 666 write_buf_len_ = 0; 667 write_socket_watcher_.StopWatchingFileDescriptor(); 668 DoWriteCallback(result); 669 } 670 } 671 672 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { 673 DCHECK(CalledOnValidThread()); 674 DCHECK(address); 675 if (!IsConnected()) 676 return ERR_SOCKET_NOT_CONNECTED; 677 address->Copy(current_ai_, false); 678 return OK; 679 } 680 681 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { 682 DCHECK(CalledOnValidThread()); 683 DCHECK(address); 684 if (!IsConnected()) 685 return ERR_SOCKET_NOT_CONNECTED; 686 687 struct sockaddr_storage addr_storage; 688 socklen_t addr_len = sizeof(addr_storage); 689 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 690 if (getsockname(socket_, addr, &addr_len)) 691 return MapSystemError(errno); 692 if (!address->FromSockAddr(addr, addr_len)) 693 return ERR_FAILED; 694 695 return OK; 696 } 697 698 const BoundNetLog& TCPClientSocketLibevent::NetLog() const { 699 return net_log_; 700 } 701 702 void TCPClientSocketLibevent::SetSubresourceSpeculation() { 703 use_history_.set_subresource_speculation(); 704 } 705 706 void TCPClientSocketLibevent::SetOmniboxSpeculation() { 707 use_history_.set_omnibox_speculation(); 708 } 709 710 bool TCPClientSocketLibevent::WasEverUsed() const { 711 return use_history_.was_used_to_convey_data(); 712 } 713 714 bool TCPClientSocketLibevent::UsingTCPFastOpen() const { 715 return use_tcp_fastopen_; 716 } 717 718 } // namespace net 719