1// Copyright 2013 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_SOCKET_LIBEVENT_H_
6#define NET_SOCKET_TCP_SOCKET_LIBEVENT_H_
7
8#include "base/basictypes.h"
9#include "base/callback.h"
10#include "base/compiler_specific.h"
11#include "base/memory/scoped_ptr.h"
12#include "net/base/address_family.h"
13#include "net/base/completion_callback.h"
14#include "net/base/net_export.h"
15#include "net/base/net_log.h"
16
17namespace net {
18
19class AddressList;
20class IOBuffer;
21class IPEndPoint;
22class SocketLibevent;
23
24class NET_EXPORT TCPSocketLibevent {
25 public:
26  TCPSocketLibevent(NetLog* net_log, const NetLog::Source& source);
27  virtual ~TCPSocketLibevent();
28
29  int Open(AddressFamily family);
30  // Takes ownership of |socket_fd|.
31  int AdoptConnectedSocket(int socket_fd, const IPEndPoint& peer_address);
32
33  int Bind(const IPEndPoint& address);
34
35  int Listen(int backlog);
36  int Accept(scoped_ptr<TCPSocketLibevent>* socket,
37             IPEndPoint* address,
38             const CompletionCallback& callback);
39
40  int Connect(const IPEndPoint& address, const CompletionCallback& callback);
41  bool IsConnected() const;
42  bool IsConnectedAndIdle() const;
43
44  // Multiple outstanding requests are not supported.
45  // Full duplex mode (reading and writing at the same time) is supported.
46  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
47  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
48
49  int GetLocalAddress(IPEndPoint* address) const;
50  int GetPeerAddress(IPEndPoint* address) const;
51
52  // Sets various socket options.
53  // The commonly used options for server listening sockets:
54  // - SetAddressReuse(true).
55  int SetDefaultOptionsForServer();
56  // The commonly used options for client sockets and accepted sockets:
57  // - SetNoDelay(true);
58  // - SetKeepAlive(true, 45).
59  void SetDefaultOptionsForClient();
60  int SetAddressReuse(bool allow);
61  int SetReceiveBufferSize(int32 size);
62  int SetSendBufferSize(int32 size);
63  bool SetKeepAlive(bool enable, int delay);
64  bool SetNoDelay(bool no_delay);
65
66  void Close();
67
68  // Setter/Getter methods for TCP FastOpen socket option.
69  bool UsingTCPFastOpen() const;
70  void EnableTCPFastOpenIfSupported();
71
72  bool IsValid() const;
73
74  // Marks the start/end of a series of connect attempts for logging purpose.
75  //
76  // TCPClientSocket may attempt to connect to multiple addresses until it
77  // succeeds in establishing a connection. The corresponding log will have
78  // multiple NetLog::TYPE_TCP_CONNECT_ATTEMPT entries nested within a
79  // NetLog::TYPE_TCP_CONNECT. These methods set the start/end of
80  // NetLog::TYPE_TCP_CONNECT.
81  //
82  // TODO(yzshen): Change logging format and let TCPClientSocket log the
83  // start/end of a series of connect attempts itself.
84  void StartLoggingMultipleConnectAttempts(const AddressList& addresses);
85  void EndLoggingMultipleConnectAttempts(int net_error);
86
87  const BoundNetLog& net_log() const { return net_log_; }
88
89 private:
90  // States that using a socket with TCP FastOpen can lead to.
91  enum FastOpenStatus {
92    FAST_OPEN_STATUS_UNKNOWN,
93
94    // The initial TCP FastOpen connect attempted returned synchronously,
95    // indicating that we had and sent a cookie along with the initial data.
96    FAST_OPEN_FAST_CONNECT_RETURN,
97
98    // The initial TCP FastOpen connect attempted returned asynchronously,
99    // indicating that we did not have a cookie for the server.
100    FAST_OPEN_SLOW_CONNECT_RETURN,
101
102    // Some other error occurred on connection, so we couldn't tell if
103    // TCP FastOpen would have worked.
104    FAST_OPEN_ERROR,
105
106    // An attempt to do a TCP FastOpen succeeded immediately
107    // (FAST_OPEN_FAST_CONNECT_RETURN) and we later confirmed that the server
108    // had acked the data we sent.
109    FAST_OPEN_SYN_DATA_ACK,
110
111    // An attempt to do a TCP FastOpen succeeded immediately
112    // (FAST_OPEN_FAST_CONNECT_RETURN) and we later confirmed that the server
113    // had nacked the data we sent.
114    FAST_OPEN_SYN_DATA_NACK,
115
116    // An attempt to do a TCP FastOpen succeeded immediately
117    // (FAST_OPEN_FAST_CONNECT_RETURN) and our probe to determine if the
118    // socket was using TCP FastOpen failed.
119    FAST_OPEN_SYN_DATA_FAILED,
120
121    // An attempt to do a TCP FastOpen failed (FAST_OPEN_SLOW_CONNECT_RETURN)
122    // and we later confirmed that the server had acked initial data.  This
123    // should never happen (we didn't send data, so it shouldn't have
124    // been acked).
125    FAST_OPEN_NO_SYN_DATA_ACK,
126
127    // An attempt to do a TCP FastOpen failed (FAST_OPEN_SLOW_CONNECT_RETURN)
128    // and we later discovered that the server had nacked initial data.  This
129    // is the expected case results for FAST_OPEN_SLOW_CONNECT_RETURN.
130    FAST_OPEN_NO_SYN_DATA_NACK,
131
132    // An attempt to do a TCP FastOpen failed (FAST_OPEN_SLOW_CONNECT_RETURN)
133    // and our later probe for ack/nack state failed.
134    FAST_OPEN_NO_SYN_DATA_FAILED,
135
136    FAST_OPEN_MAX_VALUE
137  };
138
139  void AcceptCompleted(scoped_ptr<TCPSocketLibevent>* tcp_socket,
140                       IPEndPoint* address,
141                       const CompletionCallback& callback,
142                       int rv);
143  int HandleAcceptCompleted(scoped_ptr<TCPSocketLibevent>* tcp_socket,
144                            IPEndPoint* address,
145                            int rv);
146  int BuildTcpSocketLibevent(scoped_ptr<TCPSocketLibevent>* tcp_socket,
147                             IPEndPoint* address);
148
149  void ConnectCompleted(const CompletionCallback& callback, int rv) const;
150  int HandleConnectCompleted(int rv) const;
151  void LogConnectBegin(const AddressList& addresses) const;
152  void LogConnectEnd(int net_error) const;
153
154  void ReadCompleted(const scoped_refptr<IOBuffer>& buf,
155                     const CompletionCallback& callback,
156                     int rv);
157  int HandleReadCompleted(IOBuffer* buf, int rv);
158
159  void WriteCompleted(const scoped_refptr<IOBuffer>& buf,
160                      const CompletionCallback& callback,
161                      int rv) const;
162  int HandleWriteCompleted(IOBuffer* buf, int rv) const;
163  int TcpFastOpenWrite(IOBuffer* buf,
164                       int buf_len,
165                       const CompletionCallback& callback);
166
167  // Called when the socket is known to be in a connected state.
168  void RecordFastOpenStatus();
169
170  scoped_ptr<SocketLibevent> socket_;
171  scoped_ptr<SocketLibevent> accept_socket_;
172
173  // Enables experimental TCP FastOpen option.
174  bool use_tcp_fastopen_;
175
176  // True when TCP FastOpen is in use and we have done the connect.
177  bool tcp_fastopen_connected_;
178  FastOpenStatus fast_open_status_;
179
180  bool logging_multiple_connect_attempts_;
181
182  BoundNetLog net_log_;
183
184  DISALLOW_COPY_AND_ASSIGN(TCPSocketLibevent);
185};
186
187}  // namespace net
188
189#endif  // NET_SOCKET_TCP_SOCKET_LIBEVENT_H_
190