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_SOCKS5_CLIENT_SOCKET_H_
6#define NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_
7#pragma once
8
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "googleurl/src/gurl.h"
15#include "net/base/address_list.h"
16#include "net/base/completion_callback.h"
17#include "net/base/host_resolver.h"
18#include "net/base/net_errors.h"
19#include "net/base/net_log.h"
20#include "net/socket/client_socket.h"
21#include "testing/gtest/include/gtest/gtest_prod.h"
22
23namespace net {
24
25class ClientSocketHandle;
26class BoundNetLog;
27
28// This ClientSocket is used to setup a SOCKSv5 handshake with a socks proxy.
29// Currently no SOCKSv5 authentication is supported.
30class SOCKS5ClientSocket : public ClientSocket {
31 public:
32  // Takes ownership of the |transport_socket|, which should already be
33  // connected by the time Connect() is called.
34  //
35  // |req_info| contains the hostname and port to which the socket above will
36  // communicate to via the SOCKS layer.
37  //
38  // Although SOCKS 5 supports 3 different modes of addressing, we will
39  // always pass it a hostname. This means the DNS resolving is done
40  // proxy side.
41  SOCKS5ClientSocket(ClientSocketHandle* transport_socket,
42                     const HostResolver::RequestInfo& req_info);
43
44  // Deprecated constructor (http://crbug.com/37810) that takes a ClientSocket.
45  SOCKS5ClientSocket(ClientSocket* transport_socket,
46                     const HostResolver::RequestInfo& req_info);
47
48  // On destruction Disconnect() is called.
49  virtual ~SOCKS5ClientSocket();
50
51  // ClientSocket methods:
52
53  // Does the SOCKS handshake and completes the protocol.
54  virtual int Connect(CompletionCallback* callback
55#ifdef ANDROID
56                      , bool wait_for_connect
57                      , bool valid_uid
58                      , uid_t calling_uid
59#endif
60                     );
61  virtual void Disconnect();
62  virtual bool IsConnected() const;
63  virtual bool IsConnectedAndIdle() const;
64  virtual const BoundNetLog& NetLog() const;
65  virtual void SetSubresourceSpeculation();
66  virtual void SetOmniboxSpeculation();
67  virtual bool WasEverUsed() const;
68  virtual bool UsingTCPFastOpen() const;
69
70  // Socket methods:
71  virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
72  virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
73
74  virtual bool SetReceiveBufferSize(int32 size);
75  virtual bool SetSendBufferSize(int32 size);
76
77  virtual int GetPeerAddress(AddressList* address) const;
78  virtual int GetLocalAddress(IPEndPoint* address) const;
79
80 private:
81  enum State {
82    STATE_GREET_WRITE,
83    STATE_GREET_WRITE_COMPLETE,
84    STATE_GREET_READ,
85    STATE_GREET_READ_COMPLETE,
86    STATE_HANDSHAKE_WRITE,
87    STATE_HANDSHAKE_WRITE_COMPLETE,
88    STATE_HANDSHAKE_READ,
89    STATE_HANDSHAKE_READ_COMPLETE,
90    STATE_NONE,
91  };
92
93  // Addressing type that can be specified in requests or responses.
94  enum SocksEndPointAddressType {
95    kEndPointDomain = 0x03,
96    kEndPointResolvedIPv4 = 0x01,
97    kEndPointResolvedIPv6 = 0x04,
98  };
99
100  static const unsigned int kGreetReadHeaderSize;
101  static const unsigned int kWriteHeaderSize;
102  static const unsigned int kReadHeaderSize;
103  static const uint8 kSOCKS5Version;
104  static const uint8 kTunnelCommand;
105  static const uint8 kNullByte;
106
107  void DoCallback(int result);
108  void OnIOComplete(int result);
109
110  int DoLoop(int last_io_result);
111  int DoHandshakeRead();
112  int DoHandshakeReadComplete(int result);
113  int DoHandshakeWrite();
114  int DoHandshakeWriteComplete(int result);
115  int DoGreetRead();
116  int DoGreetReadComplete(int result);
117  int DoGreetWrite();
118  int DoGreetWriteComplete(int result);
119
120  // Writes the SOCKS handshake buffer into |handshake|
121  // and return OK on success.
122  int BuildHandshakeWriteBuffer(std::string* handshake) const;
123
124  CompletionCallbackImpl<SOCKS5ClientSocket> io_callback_;
125
126  // Stores the underlying socket.
127  scoped_ptr<ClientSocketHandle> transport_;
128
129  State next_state_;
130
131  // Stores the callback to the layer above, called on completing Connect().
132  CompletionCallback* user_callback_;
133
134  // This IOBuffer is used by the class to read and write
135  // SOCKS handshake data. The length contains the expected size to
136  // read or write.
137  scoped_refptr<IOBuffer> handshake_buf_;
138
139  // While writing, this buffer stores the complete write handshake data.
140  // While reading, it stores the handshake information received so far.
141  std::string buffer_;
142
143  // This becomes true when the SOCKS handshake has completed and the
144  // overlying connection is free to communicate.
145  bool completed_handshake_;
146
147  // These contain the bytes sent / received by the SOCKS handshake.
148  size_t bytes_sent_;
149  size_t bytes_received_;
150
151  size_t read_header_size;
152
153  HostResolver::RequestInfo host_request_info_;
154
155  BoundNetLog net_log_;
156
157  DISALLOW_COPY_AND_ASSIGN(SOCKS5ClientSocket);
158};
159
160}  // namespace net
161
162#endif  // NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_
163