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#ifndef NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_
6#define NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_
7
8#include "base/memory/ref_counted.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/message_loop/message_loop.h"
11#include "base/threading/non_thread_safe.h"
12#include "net/base/address_list.h"
13#include "net/base/completion_callback.h"
14#include "net/base/net_log.h"
15#include "net/socket/stream_socket.h"
16
17namespace net {
18
19class BoundNetLog;
20
21// A client socket that uses TCP as the transport layer.
22class NET_EXPORT_PRIVATE TCPClientSocketLibevent : public StreamSocket,
23                                                   public base::NonThreadSafe {
24 public:
25  // The IP address(es) and port number to connect to.  The TCP socket will try
26  // each IP address in the list until it succeeds in establishing a
27  // connection.
28  TCPClientSocketLibevent(const AddressList& addresses,
29                          net::NetLog* net_log,
30                          const net::NetLog::Source& source);
31
32  virtual ~TCPClientSocketLibevent();
33
34  // AdoptSocket causes the given, connected socket to be adopted as a TCP
35  // socket. This object must not be connected. This object takes ownership of
36  // the given socket and then acts as if Connect() had been called. This
37  // function is used by TCPServerSocket() to adopt accepted connections
38  // and for testing.
39  int AdoptSocket(int socket);
40
41  // Binds the socket to a local IP address and port.
42  int Bind(const IPEndPoint& address);
43
44  // StreamSocket implementation.
45  virtual int Connect(const CompletionCallback& callback) OVERRIDE;
46  virtual void Disconnect() OVERRIDE;
47  virtual bool IsConnected() const OVERRIDE;
48  virtual bool IsConnectedAndIdle() const OVERRIDE;
49  virtual int GetPeerAddress(IPEndPoint* address) const OVERRIDE;
50  virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE;
51  virtual const BoundNetLog& NetLog() const OVERRIDE;
52  virtual void SetSubresourceSpeculation() OVERRIDE;
53  virtual void SetOmniboxSpeculation() OVERRIDE;
54  virtual bool WasEverUsed() const OVERRIDE;
55  virtual bool UsingTCPFastOpen() const OVERRIDE;
56  virtual bool WasNpnNegotiated() const OVERRIDE;
57  virtual NextProto GetNegotiatedProtocol() const OVERRIDE;
58  virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
59
60  // Socket implementation.
61  // Multiple outstanding requests are not supported.
62  // Full duplex mode (reading and writing at the same time) is supported
63  virtual int Read(IOBuffer* buf,
64                   int buf_len,
65                   const CompletionCallback& callback) OVERRIDE;
66  virtual int Write(IOBuffer* buf,
67                    int buf_len,
68                    const CompletionCallback& callback) OVERRIDE;
69  virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
70  virtual bool SetSendBufferSize(int32 size) OVERRIDE;
71
72  virtual bool SetKeepAlive(bool enable, int delay);
73  virtual bool SetNoDelay(bool no_delay);
74
75 private:
76  // State machine for connecting the socket.
77  enum ConnectState {
78    CONNECT_STATE_CONNECT,
79    CONNECT_STATE_CONNECT_COMPLETE,
80    CONNECT_STATE_NONE,
81  };
82
83  // States that a fast open socket attempt can result in.
84  enum FastOpenStatus {
85    FAST_OPEN_STATUS_UNKNOWN,
86
87    // The initial fast open connect attempted returned synchronously,
88    // indicating that we had and sent a cookie along with the initial data.
89    FAST_OPEN_FAST_CONNECT_RETURN,
90
91    // The initial fast open connect attempted returned asynchronously,
92    // indicating that we did not have a cookie for the server.
93    FAST_OPEN_SLOW_CONNECT_RETURN,
94
95    // Some other error occurred on connection, so we couldn't tell if
96    // fast open would have worked.
97    FAST_OPEN_ERROR,
98
99    // An attempt to do a fast open succeeded immediately
100    // (FAST_OPEN_FAST_CONNECT_RETURN) and we later confirmed that the server
101    // had acked the data we sent.
102    FAST_OPEN_SYN_DATA_ACK,
103
104    // An attempt to do a fast open succeeded immediately
105    // (FAST_OPEN_FAST_CONNECT_RETURN) and we later confirmed that the server
106    // had nacked the data we sent.
107    FAST_OPEN_SYN_DATA_NACK,
108
109    // An attempt to do a fast open succeeded immediately
110    // (FAST_OPEN_FAST_CONNECT_RETURN) and our probe to determine if the
111    // socket was using fast open failed.
112    FAST_OPEN_SYN_DATA_FAILED,
113
114    // An attempt to do a fast open failed (FAST_OPEN_SLOW_CONNECT_RETURN)
115    // and we later confirmed that the server had acked initial data.  This
116    // should never happen (we didn't send data, so it shouldn't have
117    // been acked).
118    FAST_OPEN_NO_SYN_DATA_ACK,
119
120    // An attempt to do a fast open failed (FAST_OPEN_SLOW_CONNECT_RETURN)
121    // and we later discovered that the server had nacked initial data.  This
122    // is the expected case results for FAST_OPEN_SLOW_CONNECT_RETURN.
123    FAST_OPEN_NO_SYN_DATA_NACK,
124
125    // An attempt to do a fast open failed (FAST_OPEN_SLOW_CONNECT_RETURN)
126    // and our later probe for ack/nack state failed.
127    FAST_OPEN_NO_SYN_DATA_FAILED,
128
129    FAST_OPEN_MAX_VALUE
130  };
131
132  class ReadWatcher : public base::MessageLoopForIO::Watcher {
133   public:
134    explicit ReadWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {}
135
136    // MessageLoopForIO::Watcher methods
137
138    virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE;
139
140    virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {}
141
142   private:
143    TCPClientSocketLibevent* const socket_;
144
145    DISALLOW_COPY_AND_ASSIGN(ReadWatcher);
146  };
147
148  class WriteWatcher : public base::MessageLoopForIO::Watcher {
149   public:
150    explicit WriteWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {}
151
152    // MessageLoopForIO::Watcher implementation.
153    virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {}
154    virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE;
155
156   private:
157    TCPClientSocketLibevent* const socket_;
158
159    DISALLOW_COPY_AND_ASSIGN(WriteWatcher);
160  };
161
162  // State machine used by Connect().
163  int DoConnectLoop(int result);
164  int DoConnect();
165  int DoConnectComplete(int result);
166
167  // Helper used by Disconnect(), which disconnects minus the logging and
168  // resetting of current_address_index_.
169  void DoDisconnect();
170
171  void DoReadCallback(int rv);
172  void DoWriteCallback(int rv);
173  void DidCompleteRead();
174  void DidCompleteWrite();
175  void DidCompleteConnect();
176
177  // Returns true if a Connect() is in progress.
178  bool waiting_connect() const {
179    return next_connect_state_ != CONNECT_STATE_NONE;
180  }
181
182  // Helper to add a TCP_CONNECT (end) event to the NetLog.
183  void LogConnectCompletion(int net_error);
184
185  // Internal function to write to a socket.
186  int InternalWrite(IOBuffer* buf, int buf_len);
187
188  // Called when the socket is known to be in a connected state.
189  void RecordFastOpenStatus();
190
191  int socket_;
192
193  // Local IP address and port we are bound to. Set to NULL if Bind()
194  // was't called (in that cases OS chooses address/port).
195  scoped_ptr<IPEndPoint> bind_address_;
196
197  // Stores bound socket between Bind() and Connect() calls.
198  int bound_socket_;
199
200  // The list of addresses we should try in order to establish a connection.
201  AddressList addresses_;
202
203  // Where we are in above list. Set to -1 if uninitialized.
204  int current_address_index_;
205
206  // The socket's libevent wrappers
207  base::MessageLoopForIO::FileDescriptorWatcher read_socket_watcher_;
208  base::MessageLoopForIO::FileDescriptorWatcher write_socket_watcher_;
209
210  // The corresponding watchers for reads and writes.
211  ReadWatcher read_watcher_;
212  WriteWatcher write_watcher_;
213
214  // The buffer used by OnSocketReady to retry Read requests
215  scoped_refptr<IOBuffer> read_buf_;
216  int read_buf_len_;
217
218  // The buffer used by OnSocketReady to retry Write requests
219  scoped_refptr<IOBuffer> write_buf_;
220  int write_buf_len_;
221
222  // External callback; called when read is complete.
223  CompletionCallback read_callback_;
224
225  // External callback; called when write is complete.
226  CompletionCallback write_callback_;
227
228  // The next state for the Connect() state machine.
229  ConnectState next_connect_state_;
230
231  // The OS error that CONNECT_STATE_CONNECT last completed with.
232  int connect_os_error_;
233
234  BoundNetLog net_log_;
235
236  // This socket was previously disconnected and has not been re-connected.
237  bool previously_disconnected_;
238
239  // Record of connectivity and transmissions, for use in speculative connection
240  // histograms.
241  UseHistory use_history_;
242
243  // Enables experimental TCP FastOpen option.
244  const bool use_tcp_fastopen_;
245
246  // True when TCP FastOpen is in use and we have done the connect.
247  bool tcp_fastopen_connected_;
248
249  enum FastOpenStatus fast_open_status_;
250
251  DISALLOW_COPY_AND_ASSIGN(TCPClientSocketLibevent);
252};
253
254}  // namespace net
255
256#endif  // NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_
257