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/ref_counted.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/message_loop/message_loop.h"
14#include "base/threading/non_thread_safe.h"
15#include "net/base/address_family.h"
16#include "net/base/completion_callback.h"
17#include "net/base/net_export.h"
18#include "net/base/net_log.h"
19#include "net/socket/socket_descriptor.h"
20
21namespace net {
22
23class AddressList;
24class IOBuffer;
25class IPEndPoint;
26
27class NET_EXPORT TCPSocketLibevent : public base::NonThreadSafe {
28 public:
29  TCPSocketLibevent(NetLog* net_log, const NetLog::Source& source);
30  virtual ~TCPSocketLibevent();
31
32  int Open(AddressFamily family);
33  // Takes ownership of |socket|.
34  int AdoptConnectedSocket(int socket, const IPEndPoint& peer_address);
35
36  int Bind(const IPEndPoint& address);
37
38  int Listen(int backlog);
39  int Accept(scoped_ptr<TCPSocketLibevent>* socket,
40             IPEndPoint* address,
41             const CompletionCallback& callback);
42
43  int Connect(const IPEndPoint& address, const CompletionCallback& callback);
44  bool IsConnected() const;
45  bool IsConnectedAndIdle() const;
46
47  // Multiple outstanding requests are not supported.
48  // Full duplex mode (reading and writing at the same time) is supported.
49  int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
50  int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
51
52  int GetLocalAddress(IPEndPoint* address) const;
53  int GetPeerAddress(IPEndPoint* address) const;
54
55  // Sets various socket options.
56  // The commonly used options for server listening sockets:
57  // - SetAddressReuse(true).
58  int SetDefaultOptionsForServer();
59  // The commonly used options for client sockets and accepted sockets:
60  // - SetNoDelay(true);
61  // - SetKeepAlive(true, 45).
62  void SetDefaultOptionsForClient();
63  int SetAddressReuse(bool allow);
64  int SetReceiveBufferSize(int32 size);
65  int SetSendBufferSize(int32 size);
66  bool SetKeepAlive(bool enable, int delay);
67  bool SetNoDelay(bool no_delay);
68
69  void Close();
70
71  bool UsingTCPFastOpen() const;
72  bool IsValid() const { return socket_ != kInvalidSocket; }
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 a fast open socket attempt can result in.
91  enum FastOpenStatus {
92    FAST_OPEN_STATUS_UNKNOWN,
93
94    // The initial fast open 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 fast open 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    // fast open would have worked.
104    FAST_OPEN_ERROR,
105
106    // An attempt to do a fast open 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 fast open 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 fast open succeeded immediately
117    // (FAST_OPEN_FAST_CONNECT_RETURN) and our probe to determine if the
118    // socket was using fast open failed.
119    FAST_OPEN_SYN_DATA_FAILED,
120
121    // An attempt to do a fast open 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 fast open 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 fast open 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  // Watcher simply forwards notifications to Closure objects set via the
140  // constructor.
141  class Watcher: public base::MessageLoopForIO::Watcher {
142   public:
143    Watcher(const base::Closure& read_ready_callback,
144            const base::Closure& write_ready_callback);
145    virtual ~Watcher();
146
147    // base::MessageLoopForIO::Watcher methods.
148    virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
149    virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
150
151   private:
152    base::Closure read_ready_callback_;
153    base::Closure write_ready_callback_;
154
155    DISALLOW_COPY_AND_ASSIGN(Watcher);
156  };
157
158  int AcceptInternal(scoped_ptr<TCPSocketLibevent>* socket,
159                     IPEndPoint* address);
160
161  int DoConnect();
162  void DoConnectComplete(int result);
163
164  void LogConnectBegin(const AddressList& addresses);
165  void LogConnectEnd(int net_error);
166
167  void DidCompleteRead();
168  void DidCompleteWrite();
169  void DidCompleteConnect();
170  void DidCompleteConnectOrWrite();
171  void DidCompleteAccept();
172
173  // Internal function to write to a socket. Returns an OS error.
174  int InternalWrite(IOBuffer* buf, int buf_len);
175
176  // Called when the socket is known to be in a connected state.
177  void RecordFastOpenStatus();
178
179  int socket_;
180
181  base::MessageLoopForIO::FileDescriptorWatcher accept_socket_watcher_;
182  Watcher accept_watcher_;
183
184  scoped_ptr<TCPSocketLibevent>* accept_socket_;
185  IPEndPoint* accept_address_;
186  CompletionCallback accept_callback_;
187
188  // The socket's libevent wrappers for reads and writes.
189  base::MessageLoopForIO::FileDescriptorWatcher read_socket_watcher_;
190  base::MessageLoopForIO::FileDescriptorWatcher write_socket_watcher_;
191
192  // The corresponding watchers for reads and writes.
193  Watcher read_watcher_;
194  Watcher write_watcher_;
195
196  // The buffer used for reads.
197  scoped_refptr<IOBuffer> read_buf_;
198  int read_buf_len_;
199
200  // The buffer used for writes.
201  scoped_refptr<IOBuffer> write_buf_;
202  int write_buf_len_;
203
204  // External callback; called when read is complete.
205  CompletionCallback read_callback_;
206
207  // External callback; called when write or connect is complete.
208  CompletionCallback write_callback_;
209
210  // Enables experimental TCP FastOpen option.
211  const bool use_tcp_fastopen_;
212
213  // True when TCP FastOpen is in use and we have done the connect.
214  bool tcp_fastopen_connected_;
215
216  FastOpenStatus fast_open_status_;
217
218  // A connect operation is pending. In this case, |write_callback_| needs to be
219  // called when connect is complete.
220  bool waiting_connect_;
221
222  scoped_ptr<IPEndPoint> peer_address_;
223  // The OS error that a connect attempt last completed with.
224  int connect_os_error_;
225
226  bool logging_multiple_connect_attempts_;
227
228  BoundNetLog net_log_;
229
230  DISALLOW_COPY_AND_ASSIGN(TCPSocketLibevent);
231};
232
233}  // namespace net
234
235#endif  // NET_SOCKET_TCP_SOCKET_LIBEVENT_H_
236