blob: ae3ef76d90926bf7d64e7d61c2233a92850af1e4 [file] [log] [blame]
[email protected]e0c27be2009-07-15 13:09:351// Copyright (c) 2009 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
8#include <string>
9
10#include "base/logging.h"
11#include "base/ref_counted.h"
12#include "base/scoped_ptr.h"
13#include "googleurl/src/gurl.h"
14#include "net/base/address_list.h"
15#include "net/base/completion_callback.h"
16#include "net/base/host_resolver.h"
17#include "net/base/net_errors.h"
[email protected]9e743cd2010-03-16 07:03:5318#include "net/base/net_log.h"
[email protected]e0c27be2009-07-15 13:09:3519#include "net/socket/client_socket.h"
20#include "testing/gtest/include/gtest/gtest_prod.h"
21
22namespace net {
23
[email protected]9e743cd2010-03-16 07:03:5324class BoundNetLog;
[email protected]5a05c47a2009-11-02 23:25:1925
[email protected]e0c27be2009-07-15 13:09:3526// This ClientSocket is used to setup a SOCKSv5 handshake with a socks proxy.
27// Currently no SOCKSv5 authentication is supported.
28class SOCKS5ClientSocket : public ClientSocket {
29 public:
30 // Takes ownership of the |transport_socket|, which should already be
31 // connected by the time Connect() is called.
32 //
33 // |req_info| contains the hostname and port to which the socket above will
34 // communicate to via the SOCKS layer.
[email protected]f209dba2009-12-18 00:24:3735 //
[email protected]20cbe23d2009-12-18 03:39:2136 // Although SOCKS 5 supports 3 different modes of addressing, we will
37 // always pass it a hostname. This means the DNS resolving is done
38 // proxy side.
[email protected]e0c27be2009-07-15 13:09:3539 SOCKS5ClientSocket(ClientSocket* transport_socket,
[email protected]20cbe23d2009-12-18 03:39:2140 const HostResolver::RequestInfo& req_info);
[email protected]e0c27be2009-07-15 13:09:3541
42 // On destruction Disconnect() is called.
43 virtual ~SOCKS5ClientSocket();
44
45 // ClientSocket methods:
46
47 // Does the SOCKS handshake and completes the protocol.
[email protected]9e743cd2010-03-16 07:03:5348 virtual int Connect(CompletionCallback* callback, const BoundNetLog& net_log);
[email protected]e0c27be2009-07-15 13:09:3549 virtual void Disconnect();
50 virtual bool IsConnected() const;
51 virtual bool IsConnectedAndIdle() const;
52
53 // Socket methods:
54 virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
55 virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
56
[email protected]d3f66572009-09-09 22:38:0457 virtual bool SetReceiveBufferSize(int32 size);
58 virtual bool SetSendBufferSize(int32 size);
59
[email protected]ac9eec62010-02-20 18:50:3860 virtual int GetPeerAddress(AddressList* address) const;
[email protected]e0c27be2009-07-15 13:09:3561
62 private:
[email protected]e0c27be2009-07-15 13:09:3563 enum State {
[email protected]e0c27be2009-07-15 13:09:3564 STATE_GREET_WRITE,
65 STATE_GREET_WRITE_COMPLETE,
66 STATE_GREET_READ,
67 STATE_GREET_READ_COMPLETE,
68 STATE_HANDSHAKE_WRITE,
69 STATE_HANDSHAKE_WRITE_COMPLETE,
70 STATE_HANDSHAKE_READ,
71 STATE_HANDSHAKE_READ_COMPLETE,
72 STATE_NONE,
73 };
74
[email protected]20cbe23d2009-12-18 03:39:2175 // Addressing type that can be specified in requests or responses.
[email protected]e0c27be2009-07-15 13:09:3576 enum SocksEndPointAddressType {
[email protected]20cbe23d2009-12-18 03:39:2177 kEndPointDomain = 0x03,
[email protected]e0c27be2009-07-15 13:09:3578 kEndPointResolvedIPv4 = 0x01,
79 kEndPointResolvedIPv6 = 0x04,
80 };
81
82 static const unsigned int kGreetReadHeaderSize;
83 static const unsigned int kWriteHeaderSize;
84 static const unsigned int kReadHeaderSize;
85 static const uint8 kSOCKS5Version;
86 static const uint8 kTunnelCommand;
87 static const uint8 kNullByte;
88
89 void DoCallback(int result);
90 void OnIOComplete(int result);
91
92 int DoLoop(int last_io_result);
[email protected]e0c27be2009-07-15 13:09:3593 int DoHandshakeRead();
94 int DoHandshakeReadComplete(int result);
95 int DoHandshakeWrite();
96 int DoHandshakeWriteComplete(int result);
97 int DoGreetRead();
98 int DoGreetReadComplete(int result);
99 int DoGreetWrite();
100 int DoGreetWriteComplete(int result);
101
102 // Writes the SOCKS handshake buffer into |handshake|
103 // and return OK on success.
104 int BuildHandshakeWriteBuffer(std::string* handshake) const;
105
106 CompletionCallbackImpl<SOCKS5ClientSocket> io_callback_;
107
108 // Stores the underlying socket.
109 scoped_ptr<ClientSocket> transport_;
110
111 State next_state_;
[email protected]e0c27be2009-07-15 13:09:35112
113 // Stores the callback to the layer above, called on completing Connect().
114 CompletionCallback* user_callback_;
115
116 // This IOBuffer is used by the class to read and write
117 // SOCKS handshake data. The length contains the expected size to
118 // read or write.
119 scoped_refptr<IOBuffer> handshake_buf_;
120
121 // While writing, this buffer stores the complete write handshake data.
122 // While reading, it stores the handshake information received so far.
123 std::string buffer_;
124
125 // This becomes true when the SOCKS handshake has completed and the
126 // overlying connection is free to communicate.
127 bool completed_handshake_;
128
129 // These contain the bytes sent / received by the SOCKS handshake.
130 size_t bytes_sent_;
131 size_t bytes_received_;
132
133 size_t read_header_size;
134
[email protected]e0c27be2009-07-15 13:09:35135 HostResolver::RequestInfo host_request_info_;
136
[email protected]9e743cd2010-03-16 07:03:53137 BoundNetLog net_log_;
[email protected]5a05c47a2009-11-02 23:25:19138
[email protected]e0c27be2009-07-15 13:09:35139 DISALLOW_COPY_AND_ASSIGN(SOCKS5ClientSocket);
140};
141
142} // namespace net
143
144#endif // NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_