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
38namespace net {
39
40namespace {
41
42const 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`.
48int 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.
54void 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
80int 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
105TCPClientSocketLibevent::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
137TCPClientSocketLibevent::~TCPClientSocketLibevent() {
138  Disconnect();
139  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
140}
141
142void 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
154int 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
198int 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
223int 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
288int 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
318void TCPClientSocketLibevent::Disconnect() {
319  DCHECK(CalledOnValidThread());
320
321  DoDisconnect();
322  current_ai_ = NULL;
323}
324
325void 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
345bool 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
362bool 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
380int 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
419int 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
456int 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
488bool 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
497bool 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
507int 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
514int 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
546void 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
576void 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
586void 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
596void 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
619void 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
646void 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
672int 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
681int 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
698const BoundNetLog& TCPClientSocketLibevent::NetLog() const {
699  return net_log_;
700}
701
702void TCPClientSocketLibevent::SetSubresourceSpeculation() {
703  use_history_.set_subresource_speculation();
704}
705
706void TCPClientSocketLibevent::SetOmniboxSpeculation() {
707  use_history_.set_omnibox_speculation();
708}
709
710bool TCPClientSocketLibevent::WasEverUsed() const {
711  return use_history_.was_used_to_convey_data();
712}
713
714bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
715  return use_tcp_fastopen_;
716}
717
718}  // namespace net
719