1 // 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_SOCKS_CLIENT_SOCKET_H_ 6 #define NET_SOCKET_SOCKS_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 21 namespace net { 22 23 class LoadLog; 24 25 // The SOCKS client socket implementation 26 class SOCKSClientSocket : public ClientSocket { 27 public: 28 // Takes ownership of the |transport_socket|, which should already be 29 // connected by the time Connect() is called. 30 // 31 // |req_info| contains the hostname and port to which the socket above will 32 // communicate to via the socks layer. For testing the referrer is optional. 33 SOCKSClientSocket(ClientSocket* transport_socket, 34 const HostResolver::RequestInfo& req_info, 35 HostResolver* host_resolver); 36 37 // On destruction Disconnect() is called. 38 virtual ~SOCKSClientSocket(); 39 40 // ClientSocket methods: 41 42 // Does the SOCKS handshake and completes the protocol. 43 virtual int Connect(CompletionCallback* callback, LoadLog* load_log); 44 virtual void Disconnect(); 45 virtual bool IsConnected() const; 46 virtual bool IsConnectedAndIdle() const; 47 48 // Socket methods: 49 virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); 50 virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback); 51 52 virtual bool SetReceiveBufferSize(int32 size); 53 virtual bool SetSendBufferSize(int32 size); 54 55 virtual int GetPeerName(struct sockaddr* name, socklen_t* namelen); 56 57 private: 58 FRIEND_TEST(SOCKSClientSocketTest, CompleteHandshake); 59 FRIEND_TEST(SOCKSClientSocketTest, SOCKS4AFailedDNS); 60 FRIEND_TEST(SOCKSClientSocketTest, SOCKS4AIfDomainInIPv6); 61 62 enum State { 63 STATE_RESOLVE_HOST, 64 STATE_RESOLVE_HOST_COMPLETE, 65 STATE_HANDSHAKE_WRITE, 66 STATE_HANDSHAKE_WRITE_COMPLETE, 67 STATE_HANDSHAKE_READ, 68 STATE_HANDSHAKE_READ_COMPLETE, 69 STATE_NONE, 70 }; 71 72 // The SOCKS proxy connection either has the hostname resolved via the 73 // client or via the server. This enum stores the state of the SOCKS 74 // connection. If the client can resolve the hostname, the connection is 75 // SOCKS4, otherwise it is SOCKS4A. 76 enum SocksVersion { 77 kSOCKS4Unresolved, 78 kSOCKS4, 79 kSOCKS4a, 80 }; 81 82 void DoCallback(int result); 83 void OnIOComplete(int result); 84 85 int DoLoop(int last_io_result); 86 int DoResolveHost(); 87 int DoResolveHostComplete(int result); 88 int DoHandshakeRead(); 89 int DoHandshakeReadComplete(int result); 90 int DoHandshakeWrite(); 91 int DoHandshakeWriteComplete(int result); 92 93 const std::string BuildHandshakeWriteBuffer() const; 94 95 CompletionCallbackImpl<SOCKSClientSocket> io_callback_; 96 97 // Stores the underlying socket. 98 scoped_ptr<ClientSocket> transport_; 99 100 State next_state_; 101 SocksVersion socks_version_; 102 103 // Stores the callback to the layer above, called on completing Connect(). 104 CompletionCallback* user_callback_; 105 106 // This IOBuffer is used by the class to read and write 107 // SOCKS handshake data. The length contains the expected size to 108 // read or write. 109 scoped_refptr<IOBuffer> handshake_buf_; 110 111 // While writing, this buffer stores the complete write handshake data. 112 // While reading, it stores the handshake information received so far. 113 std::string buffer_; 114 115 // This becomes true when the SOCKS handshake has completed and the 116 // overlying connection is free to communicate. 117 bool completed_handshake_; 118 119 // These contain the bytes sent / received by the SOCKS handshake. 120 size_t bytes_sent_; 121 size_t bytes_received_; 122 123 // Used to resolve the hostname to which the SOCKS proxy will connect. 124 SingleRequestHostResolver host_resolver_; 125 AddressList addresses_; 126 HostResolver::RequestInfo host_request_info_; 127 128 scoped_refptr<LoadLog> load_log_; 129 130 DISALLOW_COPY_AND_ASSIGN(SOCKSClientSocket); 131 }; 132 133 } // namespace net 134 135 #endif // NET_SOCKET_SOCKS_CLIENT_SOCKET_H_ 136