blob: f8de9a6df2dc75af5e8e09388803865ae890bc92 [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"
18#include "net/socket/client_socket.h"
19#include "testing/gtest/include/gtest/gtest_prod.h"
20
21namespace net {
22
[email protected]5a05c47a2009-11-02 23:25:1923class LoadLog;
24
[email protected]e0c27be2009-07-15 13:09:3525// This ClientSocket is used to setup a SOCKSv5 handshake with a socks proxy.
26// Currently no SOCKSv5 authentication is supported.
27class SOCKS5ClientSocket : public ClientSocket {
28 public:
29 // Takes ownership of the |transport_socket|, which should already be
30 // connected by the time Connect() is called.
31 //
32 // |req_info| contains the hostname and port to which the socket above will
33 // communicate to via the SOCKS layer.
[email protected]f209dba2009-12-18 00:24:3734 //
[email protected]20cbe23d2009-12-18 03:39:2135 // Although SOCKS 5 supports 3 different modes of addressing, we will
36 // always pass it a hostname. This means the DNS resolving is done
37 // proxy side.
[email protected]e0c27be2009-07-15 13:09:3538 SOCKS5ClientSocket(ClientSocket* transport_socket,
[email protected]20cbe23d2009-12-18 03:39:2139 const HostResolver::RequestInfo& req_info);
[email protected]e0c27be2009-07-15 13:09:3540
41 // On destruction Disconnect() is called.
42 virtual ~SOCKS5ClientSocket();
43
44 // ClientSocket methods:
45
46 // Does the SOCKS handshake and completes the protocol.
[email protected]5a05c47a2009-11-02 23:25:1947 virtual int Connect(CompletionCallback* callback, LoadLog* load_log);
[email protected]e0c27be2009-07-15 13:09:3548 virtual void Disconnect();
49 virtual bool IsConnected() const;
50 virtual bool IsConnectedAndIdle() const;
51
52 // Socket methods:
53 virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
54 virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback);
55
[email protected]d3f66572009-09-09 22:38:0456 virtual bool SetReceiveBufferSize(int32 size);
57 virtual bool SetSendBufferSize(int32 size);
58
[email protected]e0c27be2009-07-15 13:09:3559#if defined(OS_LINUX)
60 virtual int GetPeerName(struct sockaddr* name, socklen_t* namelen);
61#endif
62
63 private:
[email protected]e0c27be2009-07-15 13:09:3564 enum State {
[email protected]e0c27be2009-07-15 13:09:3565 STATE_GREET_WRITE,
66 STATE_GREET_WRITE_COMPLETE,
67 STATE_GREET_READ,
68 STATE_GREET_READ_COMPLETE,
69 STATE_HANDSHAKE_WRITE,
70 STATE_HANDSHAKE_WRITE_COMPLETE,
71 STATE_HANDSHAKE_READ,
72 STATE_HANDSHAKE_READ_COMPLETE,
73 STATE_NONE,
74 };
75
[email protected]20cbe23d2009-12-18 03:39:2176 // Addressing type that can be specified in requests or responses.
[email protected]e0c27be2009-07-15 13:09:3577 enum SocksEndPointAddressType {
[email protected]20cbe23d2009-12-18 03:39:2178 kEndPointDomain = 0x03,
[email protected]e0c27be2009-07-15 13:09:3579 kEndPointResolvedIPv4 = 0x01,
80 kEndPointResolvedIPv6 = 0x04,
81 };
82
83 static const unsigned int kGreetReadHeaderSize;
84 static const unsigned int kWriteHeaderSize;
85 static const unsigned int kReadHeaderSize;
86 static const uint8 kSOCKS5Version;
87 static const uint8 kTunnelCommand;
88 static const uint8 kNullByte;
89
90 void DoCallback(int result);
91 void OnIOComplete(int result);
92
93 int DoLoop(int last_io_result);
[email protected]e0c27be2009-07-15 13:09:3594 int DoHandshakeRead();
95 int DoHandshakeReadComplete(int result);
96 int DoHandshakeWrite();
97 int DoHandshakeWriteComplete(int result);
98 int DoGreetRead();
99 int DoGreetReadComplete(int result);
100 int DoGreetWrite();
101 int DoGreetWriteComplete(int result);
102
103 // Writes the SOCKS handshake buffer into |handshake|
104 // and return OK on success.
105 int BuildHandshakeWriteBuffer(std::string* handshake) const;
106
107 CompletionCallbackImpl<SOCKS5ClientSocket> io_callback_;
108
109 // Stores the underlying socket.
110 scoped_ptr<ClientSocket> transport_;
111
112 State next_state_;
[email protected]e0c27be2009-07-15 13:09:35113
114 // Stores the callback to the layer above, called on completing Connect().
115 CompletionCallback* user_callback_;
116
117 // This IOBuffer is used by the class to read and write
118 // SOCKS handshake data. The length contains the expected size to
119 // read or write.
120 scoped_refptr<IOBuffer> handshake_buf_;
121
122 // While writing, this buffer stores the complete write handshake data.
123 // While reading, it stores the handshake information received so far.
124 std::string buffer_;
125
126 // This becomes true when the SOCKS handshake has completed and the
127 // overlying connection is free to communicate.
128 bool completed_handshake_;
129
130 // These contain the bytes sent / received by the SOCKS handshake.
131 size_t bytes_sent_;
132 size_t bytes_received_;
133
134 size_t read_header_size;
135
[email protected]e0c27be2009-07-15 13:09:35136 HostResolver::RequestInfo host_request_info_;
137
[email protected]5a05c47a2009-11-02 23:25:19138 scoped_refptr<LoadLog> load_log_;
139
[email protected]e0c27be2009-07-15 13:09:35140 DISALLOW_COPY_AND_ASSIGN(SOCKS5ClientSocket);
141};
142
143} // namespace net
144
145#endif // NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_