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 17 namespace net { 18 19 class BoundNetLog; 20 21 // A client socket that uses TCP as the transport layer. 22 class 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