diff options
author | arindam@chromium.org <arindam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-15 13:09:35 +0000 |
---|---|---|
committer | arindam@chromium.org <arindam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-15 13:09:35 +0000 |
commit | e0c27beabdf16ead25bfba3b7db2965efef19ee1 (patch) | |
tree | 5ca10d12fef6ac96d56f3555d50480398c4ba42d /net/socket/socks5_client_socket.h | |
parent | 40932550f6416f8c9fb66717aa5c7528fc082675 (diff) | |
download | chromium_src-e0c27beabdf16ead25bfba3b7db2965efef19ee1.zip chromium_src-e0c27beabdf16ead25bfba3b7db2965efef19ee1.tar.gz chromium_src-e0c27beabdf16ead25bfba3b7db2965efef19ee1.tar.bz2 |
SOCKS v5 implementation
The implementation is incomplete as it does not support any authentication methods and does not have a UDP layer.
BUG=469
TEST=unittests (included)
Review URL: http://codereview.chromium.org/150187
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20724 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/socks5_client_socket.h')
-rw-r--r-- | net/socket/socks5_client_socket.h | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h new file mode 100644 index 0000000..1a5672d --- /dev/null +++ b/net/socket/socks5_client_socket.h @@ -0,0 +1,151 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_ +#define NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_ + +#include <string> + +#include "base/logging.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "googleurl/src/gurl.h" +#include "net/base/address_list.h" +#include "net/base/completion_callback.h" +#include "net/base/host_resolver.h" +#include "net/base/net_errors.h" +#include "net/socket/client_socket.h" +#include "testing/gtest/include/gtest/gtest_prod.h" + +namespace net { + +// This ClientSocket is used to setup a SOCKSv5 handshake with a socks proxy. +// Currently no SOCKSv5 authentication is supported. +class SOCKS5ClientSocket : public ClientSocket { + public: + // Takes ownership of the |transport_socket|, which should already be + // connected by the time Connect() is called. + // + // |req_info| contains the hostname and port to which the socket above will + // communicate to via the SOCKS layer. + SOCKS5ClientSocket(ClientSocket* transport_socket, + const HostResolver::RequestInfo& req_info, + HostResolver* host_resolver); + + // On destruction Disconnect() is called. + virtual ~SOCKS5ClientSocket(); + + // ClientSocket methods: + + // Does the SOCKS handshake and completes the protocol. + virtual int Connect(CompletionCallback* callback); + virtual void Disconnect(); + virtual bool IsConnected() const; + virtual bool IsConnectedAndIdle() const; + + // Socket methods: + virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); + virtual int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback); + +#if defined(OS_LINUX) + virtual int GetPeerName(struct sockaddr* name, socklen_t* namelen); +#endif + + private: + FRIEND_TEST(SOCKS5ClientSocketTest, IPv6Domain); + FRIEND_TEST(SOCKS5ClientSocketTest, FailedDNS); + FRIEND_TEST(SOCKS5ClientSocketTest, CompleteHandshake); + + enum State { + STATE_RESOLVE_HOST, + STATE_RESOLVE_HOST_COMPLETE, + STATE_GREET_WRITE, + STATE_GREET_WRITE_COMPLETE, + STATE_GREET_READ, + STATE_GREET_READ_COMPLETE, + STATE_HANDSHAKE_WRITE, + STATE_HANDSHAKE_WRITE_COMPLETE, + STATE_HANDSHAKE_READ, + STATE_HANDSHAKE_READ_COMPLETE, + STATE_NONE, + }; + + // State of the SOCKSv5 handshake. Before host resolution all connections + // are kEndPointFailedDomain. If DNS lookup fails, we move to + // kEndPointFailedDomain, otherwise the IPv4/IPv6 address as resolved. + enum SocksEndPointAddressType { + kEndPointUnresolved, + kEndPointFailedDomain = 0x03, + kEndPointResolvedIPv4 = 0x01, + kEndPointResolvedIPv6 = 0x04, + }; + + static const unsigned int kGreetReadHeaderSize; + static const unsigned int kWriteHeaderSize; + static const unsigned int kReadHeaderSize; + static const uint8 kSOCKS5Version; + static const uint8 kTunnelCommand; + static const uint8 kNullByte; + + void DoCallback(int result); + void OnIOComplete(int result); + + int DoLoop(int last_io_result); + int DoResolveHost(); + int DoResolveHostComplete(int result); + int DoHandshakeRead(); + int DoHandshakeReadComplete(int result); + int DoHandshakeWrite(); + int DoHandshakeWriteComplete(int result); + int DoGreetRead(); + int DoGreetReadComplete(int result); + int DoGreetWrite(); + int DoGreetWriteComplete(int result); + + // Writes the SOCKS handshake buffer into |handshake| + // and return OK on success. + int BuildHandshakeWriteBuffer(std::string* handshake) const; + + CompletionCallbackImpl<SOCKS5ClientSocket> io_callback_; + + // Stores the underlying socket. + scoped_ptr<ClientSocket> transport_; + + State next_state_; + SocksEndPointAddressType address_type_; + + // Stores the callback to the layer above, called on completing Connect(). + CompletionCallback* user_callback_; + + // This IOBuffer is used by the class to read and write + // SOCKS handshake data. The length contains the expected size to + // read or write. + scoped_refptr<IOBuffer> handshake_buf_; + + // While writing, this buffer stores the complete write handshake data. + // While reading, it stores the handshake information received so far. + std::string buffer_; + + // This becomes true when the SOCKS handshake has completed and the + // overlying connection is free to communicate. + bool completed_handshake_; + + // These contain the bytes sent / received by the SOCKS handshake. + size_t bytes_sent_; + size_t bytes_received_; + + size_t read_header_size; + + // Used to resolve the hostname to which the SOCKS proxy will connect. + SingleRequestHostResolver host_resolver_; + AddressList addresses_; + HostResolver::RequestInfo host_request_info_; + + DISALLOW_COPY_AND_ASSIGN(SOCKS5ClientSocket); +}; + +} // namespace net + +#endif // NET_SOCKET_SOCKS5_CLIENT_SOCKET_H_ + |