Home | History | Annotate | Download | only in socket
      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