1// Copyright (c) 2011 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#pragma once
8
9#include "base/memory/ref_counted.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/message_loop.h"
12#include "base/threading/non_thread_safe.h"
13#include "net/base/address_list.h"
14#include "net/base/completion_callback.h"
15#include "net/base/net_log.h"
16#include "net/socket/client_socket.h"
17
18struct event;  // From libevent
19
20namespace net {
21
22class BoundNetLog;
23
24// A client socket that uses TCP as the transport layer.
25class TCPClientSocketLibevent : public ClientSocket, base::NonThreadSafe {
26 public:
27  // The IP address(es) and port number to connect to.  The TCP socket will try
28  // each IP address in the list until it succeeds in establishing a
29  // connection.
30  TCPClientSocketLibevent(const AddressList& addresses,
31                          net::NetLog* net_log,
32                          const net::NetLog::Source& source);
33
34  virtual ~TCPClientSocketLibevent();
35
36  // AdoptSocket causes the given, connected socket to be adopted as a TCP
37  // socket. This object must not be connected. This object takes ownership of
38  // the given socket and then acts as if Connect() had been called. This
39  // function is used by TCPServerSocket() to adopt accepted connections
40  // and for testing.
41  void AdoptSocket(int socket);
42
43  // ClientSocket methods:
44  virtual int Connect(CompletionCallback* callback
45#ifdef ANDROID
46                      , bool wait_for_connect
47                      , bool valid_uid
48                      , uid_t calling_uid
49#endif
50                     );
51  virtual void Disconnect();
52  virtual bool IsConnected() const;
53  virtual bool IsConnectedAndIdle() const;
54  virtual int GetPeerAddress(AddressList* address) const;
55  virtual int GetLocalAddress(IPEndPoint* address) const;
56  virtual const BoundNetLog& NetLog() const;
57  virtual void SetSubresourceSpeculation();
58  virtual void SetOmniboxSpeculation();
59  virtual bool WasEverUsed() const;
60  virtual bool UsingTCPFastOpen() const;
61
62  // Socket methods:
63  // Multiple outstanding requests are not supported.
64  // Full duplex mode (reading and writing at the same time) is supported
65  virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
66  virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
67  virtual bool SetReceiveBufferSize(int32 size);
68  virtual bool SetSendBufferSize(int32 size);
69
70 private:
71  // State machine for connecting the socket.
72  enum ConnectState {
73    CONNECT_STATE_CONNECT,
74    CONNECT_STATE_CONNECT_COMPLETE,
75    CONNECT_STATE_NONE,
76  };
77
78  class ReadWatcher : public MessageLoopForIO::Watcher {
79   public:
80    explicit ReadWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {}
81
82    // MessageLoopForIO::Watcher methods
83
84    virtual void OnFileCanReadWithoutBlocking(int /* fd */) {
85      if (socket_->read_callback_)
86        socket_->DidCompleteRead();
87    }
88
89    virtual void OnFileCanWriteWithoutBlocking(int /* fd */) {}
90
91   private:
92    TCPClientSocketLibevent* const socket_;
93
94    DISALLOW_COPY_AND_ASSIGN(ReadWatcher);
95  };
96
97  class WriteWatcher : public MessageLoopForIO::Watcher {
98   public:
99    explicit WriteWatcher(TCPClientSocketLibevent* socket) : socket_(socket) {}
100
101    // MessageLoopForIO::Watcher methods
102
103    virtual void OnFileCanReadWithoutBlocking(int /* fd */) {}
104
105    virtual void OnFileCanWriteWithoutBlocking(int /* fd */) {
106      if (socket_->waiting_connect()) {
107        socket_->DidCompleteConnect();
108      } else if (socket_->write_callback_) {
109        socket_->DidCompleteWrite();
110      }
111    }
112
113   private:
114    TCPClientSocketLibevent* const socket_;
115
116    DISALLOW_COPY_AND_ASSIGN(WriteWatcher);
117  };
118
119  // State machine used by Connect().
120  int DoConnectLoop(int result);
121  int DoConnect();
122  int DoConnectComplete(int result);
123
124  // Helper used by Disconnect(), which disconnects minus the logging and
125  // resetting of current_ai_.
126  void DoDisconnect();
127
128  void DoReadCallback(int rv);
129  void DoWriteCallback(int rv);
130  void DidCompleteRead();
131  void DidCompleteWrite();
132  void DidCompleteConnect();
133
134  // Returns true if a Connect() is in progress.
135  bool waiting_connect() const {
136    return next_connect_state_ != CONNECT_STATE_NONE;
137  }
138
139  // Returns the OS error code (or 0 on success).
140  int CreateSocket(const struct addrinfo* ai);
141
142  // Returns the OS error code (or 0 on success).
143  int SetupSocket();
144
145  // Helper to add a TCP_CONNECT (end) event to the NetLog.
146  void LogConnectCompletion(int net_error);
147
148  // Internal function to write to a socket.
149  int InternalWrite(IOBuffer* buf, int buf_len);
150
151  int socket_;
152
153  // The list of addresses we should try in order to establish a connection.
154  AddressList addresses_;
155
156  // Where we are in above list, or NULL if all addrinfos have been tried.
157  const struct addrinfo* current_ai_;
158
159  // The socket's libevent wrappers
160  MessageLoopForIO::FileDescriptorWatcher read_socket_watcher_;
161  MessageLoopForIO::FileDescriptorWatcher write_socket_watcher_;
162
163  // The corresponding watchers for reads and writes.
164  ReadWatcher read_watcher_;
165  WriteWatcher write_watcher_;
166
167  // The buffer used by OnSocketReady to retry Read requests
168  scoped_refptr<IOBuffer> read_buf_;
169  int read_buf_len_;
170
171  // The buffer used by OnSocketReady to retry Write requests
172  scoped_refptr<IOBuffer> write_buf_;
173  int write_buf_len_;
174
175  // External callback; called when read is complete.
176  CompletionCallback* read_callback_;
177
178  // External callback; called when write is complete.
179  CompletionCallback* write_callback_;
180
181  // The next state for the Connect() state machine.
182  ConnectState next_connect_state_;
183
184  // The OS error that CONNECT_STATE_CONNECT last completed with.
185  int connect_os_error_;
186
187  BoundNetLog net_log_;
188
189  // This socket was previously disconnected and has not been re-connected.
190  bool previously_disconnected_;
191
192  // Record of connectivity and transmissions, for use in speculative connection
193  // histograms.
194  UseHistory use_history_;
195
196  // Enables experimental TCP FastOpen option.
197  bool use_tcp_fastopen_;
198
199  // True when TCP FastOpen is in use and we have done the connect.
200  bool tcp_fastopen_connected_;
201
202#ifdef ANDROID
203  // True if connect should block and not return before the socket is connected
204  bool wait_for_connect_;
205  bool valid_uid_;
206  uid_t calling_uid_;
207#endif
208  DISALLOW_COPY_AND_ASSIGN(TCPClientSocketLibevent);
209};
210
211}  // namespace net
212
213#endif  // NET_SOCKET_TCP_CLIENT_SOCKET_LIBEVENT_H_
214