tcp_client_socket.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/callback_helpers.h"
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/logging.h"
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/io_buffer.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/ip_endpoint.h"
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/net_errors.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/base/net_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TCPClientSocket::TCPClientSocket(const AddressList& addresses,
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 net::NetLog* net_log,
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 const net::NetLog::Source& source)
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    : socket_(new TCPSocket(net_log, source)),
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      addresses_(addresses),
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      current_address_index_(-1),
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      next_connect_state_(CONNECT_STATE_NONE),
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      previously_disconnected_(false) {
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TCPClientSocket::TCPClientSocket(scoped_ptr<TCPSocket> connected_socket,
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                 const IPEndPoint& peer_address)
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    : socket_(connected_socket.Pass()),
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      addresses_(AddressList(peer_address)),
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      current_address_index_(0),
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      next_connect_state_(CONNECT_STATE_NONE),
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      previously_disconnected_(false) {
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(socket_);
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  socket_->SetDefaultOptionsForClient();
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  use_history_.set_was_ever_connected();
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TCPClientSocket::~TCPClientSocket() {
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::Bind(const IPEndPoint& address) {
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (current_address_index_ >= 0 || bind_address_) {
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Cannot bind the socket if we are already connected or connecting.
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    NOTREACHED();
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return ERR_UNEXPECTED;
47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int result = OK;
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!socket_->IsValid()) {
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    result = OpenSocket(address.GetFamily());
52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (result != OK)
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return result;
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  result = socket_->Bind(address);
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result != OK)
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return result;
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bind_address_.reset(new IPEndPoint(address));
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return OK;
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::Connect(const CompletionCallback& callback) {
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!callback.is_null());
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If connecting or already connected, then just return OK.
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (socket_->IsValid() && current_address_index_ >= 0)
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return OK;
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  socket_->StartLoggingMultipleConnectAttempts(addresses_);
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We will try to connect to each address in addresses_. Start with the
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // first one in the list.
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  next_connect_state_ = CONNECT_STATE_CONNECT;
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  current_address_index_ = 0;
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int rv = DoConnectLoop(OK);
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (rv == ERR_IO_PENDING) {
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    connect_callback_ = callback;
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } else {
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    socket_->EndLoggingMultipleConnectAttempts(rv);
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return rv;
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::DoConnectLoop(int result) {
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int rv = result;
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  do {
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ConnectState state = next_connect_state_;
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    next_connect_state_ = CONNECT_STATE_NONE;
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    switch (state) {
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      case CONNECT_STATE_CONNECT:
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        DCHECK_EQ(OK, rv);
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        rv = DoConnect();
99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      case CONNECT_STATE_CONNECT_COMPLETE:
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        rv = DoConnectComplete(rv);
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      default:
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        NOTREACHED() << "bad state " << state;
105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        rv = ERR_UNEXPECTED;
106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return rv;
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::DoConnect() {
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_GE(current_address_index_, 0);
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const IPEndPoint& endpoint = addresses_[current_address_index_];
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (previously_disconnected_) {
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    use_history_.Reset();
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    previously_disconnected_ = false;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (socket_->IsValid()) {
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(bind_address_);
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } else {
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int result = OpenSocket(endpoint.GetFamily());
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (result != OK)
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return result;
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (bind_address_) {
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      result = socket_->Bind(*bind_address_);
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (result != OK) {
136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        socket_->Close();
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return result;
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |socket_| is owned by this class and the callback won't be run once
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->Connect(endpoint,
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          base::Bind(&TCPClientSocket::DidCompleteConnect,
146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     base::Unretained(this)));
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::DoConnectComplete(int result) {
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result == OK) {
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    use_history_.set_was_ever_connected();
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return OK;  // Done!
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Close whatever partially connected socket we currently have.
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DoDisconnect();
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Try to fall back to the next address in the list.
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    next_connect_state_ = CONNECT_STATE_CONNECT;
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ++current_address_index_;
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return OK;
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Otherwise there is nothing to fall back to, so give up.
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return result;
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPClientSocket::Disconnect() {
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DoDisconnect();
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  current_address_index_ = -1;
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bind_address_.reset();
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPClientSocket::DoDisconnect() {
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If connecting or already connected, record that the socket has been
177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // disconnected.
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  previously_disconnected_ = socket_->IsValid() && current_address_index_ >= 0;
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  socket_->Close();
180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::IsConnected() const {
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->IsConnected();
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::IsConnectedAndIdle() const {
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->IsConnectedAndIdle();
188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::GetPeerAddress(IPEndPoint* address) const {
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->GetPeerAddress(address);
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::GetLocalAddress(IPEndPoint* address) const {
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(address);
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!socket_->IsValid()) {
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (bind_address_) {
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      *address = *bind_address_;
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return OK;
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->GetLocalAddress(address);
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const BoundNetLog& TCPClientSocket::NetLog() const {
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->net_log();
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPClientSocket::SetSubresourceSpeculation() {
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  use_history_.set_subresource_speculation();
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPClientSocket::SetOmniboxSpeculation() {
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  use_history_.set_omnibox_speculation();
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::WasEverUsed() const {
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return use_history_.was_used_to_convey_data();
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::UsingTCPFastOpen() const {
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->UsingTCPFastOpen();
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid TCPClientSocket::EnableTCPFastOpenIfSupported() {
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  socket_->EnableTCPFastOpenIfSupported();
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::WasNpnNegotiated() const {
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return false;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)NextProto TCPClientSocket::GetNegotiatedProtocol() const {
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return kProtoUnknown;
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::Read(IOBuffer* buf,
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          int buf_len,
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                          const CompletionCallback& callback) {
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!callback.is_null());
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |socket_| is owned by this class and the callback won't be run once
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CompletionCallback read_callback = base::Bind(
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      &TCPClientSocket::DidCompleteReadWrite, base::Unretained(this), callback);
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int result = socket_->Read(buf, buf_len, read_callback);
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result > 0)
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    use_history_.set_was_used_to_convey_data();
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return result;
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::Write(IOBuffer* buf,
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                           int buf_len,
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                           const CompletionCallback& callback) {
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!callback.is_null());
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |socket_| is owned by this class and the callback won't be run once
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // |socket_| is gone. Therefore, it is safe to use base::Unretained() here.
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CompletionCallback write_callback = base::Bind(
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      &TCPClientSocket::DidCompleteReadWrite, base::Unretained(this), callback);
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int result = socket_->Write(buf, buf_len, write_callback);
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result > 0)
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    use_history_.set_was_used_to_convey_data();
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return result;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TCPClientSocket::SetReceiveBufferSize(int32 size) {
277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->SetReceiveBufferSize(size);
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint TCPClientSocket::SetSendBufferSize(int32 size) {
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return socket_->SetSendBufferSize(size);
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::SetKeepAlive(bool enable, int delay) {
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->SetKeepAlive(enable, delay);
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool TCPClientSocket::SetNoDelay(bool no_delay) {
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return socket_->SetNoDelay(no_delay);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPClientSocket::DidCompleteConnect(int result) {
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_NE(result, ERR_IO_PENDING);
295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!connect_callback_.is_null());
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  result = DoConnectLoop(result);
298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result != ERR_IO_PENDING) {
299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    socket_->EndLoggingMultipleConnectAttempts(result);
300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::ResetAndReturn(&connect_callback_).Run(result);
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void TCPClientSocket::DidCompleteReadWrite(const CompletionCallback& callback,
305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                           int result) {
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result > 0)
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    use_history_.set_was_used_to_convey_data();
308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  callback.Run(result);
310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int TCPClientSocket::OpenSocket(AddressFamily family) {
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!socket_->IsValid());
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int result = socket_->Open(family);
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result != OK)
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return result;
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  socket_->SetDefaultOptionsForClient();
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return OK;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
325