http_proxy.h revision f65320cc1c04ea9e09cc8656e87fe9912c601e9a
1f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 2f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// Use of this source code is governed by a BSD-style license that can be 3f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// found in the LICENSE file. 4f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 5f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#ifndef SHILL_HTTP_PROXY_ 6f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#define SHILL_HTTP_PROXY_ 7f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 8f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <string> 9f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <vector> 10f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 11f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <base/callback_old.h> 12f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <base/memory/ref_counted.h> 13f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <base/memory/scoped_ptr.h> 14f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <base/task.h> 15f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 16f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/byte_string.h" 17f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/refptr_types.h" 18f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 19f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartnamespace shill { 20f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 21f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass AsyncConnection; 22f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass EventDispatcher; 23f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass DNSClient; 24f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass InputData; 25f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass IOHandler; 26f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass IPAddress; 27f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass Sockets; 28f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 29f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// The HTTPProxy class implements a simple web proxy that 30f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// is bound to a specific interface and name server. This 31f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// allows us to specify which connection a URL should be 32f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// fetched through, even though many connections 33f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// could be active at the same time. 34f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// 35f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// This service is meant to be low-performance, since we 36f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// do not want to divert resources from the rest of the 37f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// connection manager. As such, we serve one client request 38f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// at a time. This is probably okay since the use case is 39f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// limited -- only portal detection, activation and Cashew 40f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// are planned to be full-time users. 41f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass HTTPProxy { 42f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart public: 43f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart enum State { 44f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateIdle, 45f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateWaitConnection, 46f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateReadClientHeader, 47f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateLookupServer, 48f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateConnectServer, 49f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateTunnelData, 50f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateFlushResponse, 51f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart }; 52f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 53f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart HTTPProxy(const std::string &interface_name, 54f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart const std::vector<std::string> &dns_servers); 55f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart virtual ~HTTPProxy(); 56f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 57f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Start HTTP proxy. 58f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool Start(EventDispatcher *dispatcher, Sockets *sockets); 59f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 60f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Shutdown. 61f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void Stop(); 62f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 63f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int proxy_port() const { return proxy_port_; } 64f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 65f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart private: 66f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart friend class HTTPProxyTest; 67f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 68f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for initial headers from client. 69f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kClientHeaderTimeoutSeconds; 70f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for connection to remote server. 71f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kConnectTimeoutSeconds; 72f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for DNS server. 73f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kDNSTimeoutSeconds; 74f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Default port on remote server to connect to. 75f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kDefaultServerPort; 76f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for any input from either server or client. 77f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kInputTimeoutSeconds; 78f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Maximum clients to be kept waiting. 79f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const size_t kMaxClientQueue; 80f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Maximum number of header lines to accept. 81f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const size_t kMaxHeaderCount; 82f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Maximum length of an individual header line. 83f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const size_t kMaxHeaderSize; 84f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Timeout for whole transaction. 85f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kTransactionTimeoutSeconds; 86f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 87f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPURLDelimiters[]; 88f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPURLPrefix[]; 89f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPVersionPrefix[]; 90f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPVersionErrorMsg[]; 91f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kInternalErrorMsg[]; // Message to send on failure. 92f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 93f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void AcceptClient(int fd); 94f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ConnectServer(const IPAddress &address, int port); 95f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void GetDNSResult(bool result); 96f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void OnConnectCompletion(bool success, int fd); 97f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ParseClientRequest(); 98f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ProcessLastHeaderLine(); 99f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ReadClientHeaders(InputData *data); 100f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ReadClientHostname(std::string *header); 101f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ReadClientHTTPVersion(std::string *header); 102f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void ReadFromClient(InputData *data); 103f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void ReadFromServer(InputData *data); 104f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void SendClientError(int code, const std::string &error); 105f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StartIdleTimeout(); 106f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StartReceive(); 107f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StartTransmit(); 108f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StopClient(); 109f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void WriteToClient(int fd); 110f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void WriteToServer(int fd); 111f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 112f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // State held for the lifetime of the proxy. 113f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart State state_; 114f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart const std::string interface_name_; 115f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::vector<std::string> dns_servers_; 116f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback1<int>::Type> accept_callback_; 117f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback2<bool, int>::Type> connect_completion_callback_; 118f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback1<bool>::Type> dns_client_callback_; 119f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback1<InputData *>::Type> read_client_callback_; 120f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback1<InputData *>::Type> read_server_callback_; 121f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback1<int>::Type> write_client_callback_; 122f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<Callback1<int>::Type> write_server_callback_; 123f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart ScopedRunnableMethodFactory<HTTPProxy> task_factory_; 124f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 125f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // State held while proxy is started (even if no transaction is active). 126f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<IOHandler> accept_handler_; 127f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart EventDispatcher *dispatcher_; 128f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<DNSClient> dns_client_; 129f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int proxy_port_; 130f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int proxy_socket_; 131f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<AsyncConnection> server_async_connection_; 132f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart Sockets *sockets_; 133f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 134f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // State held while proxy is started and a transaction is active. 135f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int client_socket_; 136f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::string client_version_; 137f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int server_port_; 138f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int server_socket_; 139f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart CancelableTask *idle_timeout_; 140f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::vector<std::string> client_headers_; 141f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::string server_hostname_; 142f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart ByteString client_data_; 143f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart ByteString server_data_; 144f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<IOHandler> read_client_handler_; 145f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<IOHandler> write_client_handler_; 146f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<IOHandler> read_server_handler_; 147f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart scoped_ptr<IOHandler> write_server_handler_; 148f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 149f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart DISALLOW_COPY_AND_ASSIGN(HTTPProxy); 150f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}; 151f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 152f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart} // namespace shill 153f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 154f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#endif // SHILL_HTTP_PROXY_ 155