1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 16f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 17c45688bb3881f0c2216e6ec0e19ebda0be33e871Ben Chan#ifndef SHILL_HTTP_PROXY_H_ 18c45688bb3881f0c2216e6ec0e19ebda0be33e871Ben Chan#define SHILL_HTTP_PROXY_H_ 19f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 20cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan#include <memory> 21f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <string> 22f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <vector> 23f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 243e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/cancelable_callback.h> 25f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <base/memory/ref_counted.h> 263e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/memory/weak_ptr.h> 27f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 288d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/byte_string.h" 29f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/refptr_types.h" 30f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 31f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartnamespace shill { 32f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 33f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass AsyncConnection; 34f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass DNSClient; 35bdb02e664f79f29b3bce9be4ca05c82d8ede697fPaul Stewartclass Error; 36bdb02e664f79f29b3bce9be4ca05c82d8ede697fPaul Stewartclass EventDispatcher; 37f4baef2e49c144b8dad650562c60e03b8407ef17Liam McLoughlinstruct InputData; 38f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass IOHandler; 39f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass IPAddress; 40f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass Sockets; 41f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 42f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// The HTTPProxy class implements a simple web proxy that 43f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// is bound to a specific interface and name server. This 44f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// allows us to specify which connection a URL should be 45f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// fetched through, even though many connections 46f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// could be active at the same time. 47f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// 48f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// This service is meant to be low-performance, since we 49f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// do not want to divert resources from the rest of the 50f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// connection manager. As such, we serve one client request 51f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// at a time. This is probably okay since the use case is 52f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// limited -- only portal detection, activation and Cashew 53f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// are planned to be full-time users. 54f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass HTTPProxy { 55f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart public: 56f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart enum State { 57f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateIdle, 58f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateWaitConnection, 59f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateReadClientHeader, 60f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateLookupServer, 61f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateConnectServer, 62f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateTunnelData, 63f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart kStateFlushResponse, 64f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart }; 65f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 66c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart explicit HTTPProxy(ConnectionRefPtr connection); 67f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart virtual ~HTTPProxy(); 68f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 69f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Start HTTP proxy. 708ae18741780300de3126826b72593391f2d00313Paul Stewart bool Start(EventDispatcher* dispatcher, Sockets* sockets); 71f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 72f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Shutdown. 73f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void Stop(); 74f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 75f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int proxy_port() const { return proxy_port_; } 76f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 77f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart private: 78f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart friend class HTTPProxyTest; 79f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 80f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for initial headers from client. 81f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kClientHeaderTimeoutSeconds; 82f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for connection to remote server. 83f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kConnectTimeoutSeconds; 84f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for DNS server. 85f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kDNSTimeoutSeconds; 86f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Default port on remote server to connect to. 87f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kDefaultServerPort; 88f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Time to wait for any input from either server or client. 89f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kInputTimeoutSeconds; 90f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Maximum clients to be kept waiting. 91f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const size_t kMaxClientQueue; 92f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Maximum number of header lines to accept. 93f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const size_t kMaxHeaderCount; 94f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Maximum length of an individual header line. 95f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const size_t kMaxHeaderSize; 96f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // Timeout for whole transaction. 97f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const int kTransactionTimeoutSeconds; 98f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 9958a577b23de1478a72135410d146625ffd00e909Paul Stewart static const char kHTTPMethodConnect[]; 10058a577b23de1478a72135410d146625ffd00e909Paul Stewart static const char kHTTPMethodTerminator[]; 101f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPURLDelimiters[]; 102f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPURLPrefix[]; 103f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPVersionPrefix[]; 104f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kHTTPVersionErrorMsg[]; 105f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart static const char kInternalErrorMsg[]; // Message to send on failure. 106f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 107f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void AcceptClient(int fd); 1088ae18741780300de3126826b72593391f2d00313Paul Stewart bool ConnectServer(const IPAddress& address, int port); 1098ae18741780300de3126826b72593391f2d00313Paul Stewart void GetDNSResult(const Error& error, const IPAddress& address); 1108ae18741780300de3126826b72593391f2d00313Paul Stewart void OnReadError(const std::string& error_msg); 111f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void OnConnectCompletion(bool success, int fd); 112f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ParseClientRequest(); 113f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart bool ProcessLastHeaderLine(); 1148ae18741780300de3126826b72593391f2d00313Paul Stewart bool ReadClientHeaders(InputData* data); 1158ae18741780300de3126826b72593391f2d00313Paul Stewart bool ReadClientHostname(std::string* header); 1168ae18741780300de3126826b72593391f2d00313Paul Stewart bool ReadClientHTTPMethod(std::string* header); 1178ae18741780300de3126826b72593391f2d00313Paul Stewart bool ReadClientHTTPVersion(std::string* header); 1188ae18741780300de3126826b72593391f2d00313Paul Stewart void ReadFromClient(InputData* data); 1198ae18741780300de3126826b72593391f2d00313Paul Stewart void ReadFromServer(InputData* data); 1208ae18741780300de3126826b72593391f2d00313Paul Stewart void SetClientResponse(int code, const std::string& type, 1218ae18741780300de3126826b72593391f2d00313Paul Stewart const std::string& content_type, 1228ae18741780300de3126826b72593391f2d00313Paul Stewart const std::string& message); 1238ae18741780300de3126826b72593391f2d00313Paul Stewart void SendClientError(int code, const std::string& error); 124f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StartIdleTimeout(); 125f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StartReceive(); 126f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StartTransmit(); 127f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void StopClient(); 128f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void WriteToClient(int fd); 129f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart void WriteToServer(int fd); 130f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 131f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // State held for the lifetime of the proxy. 132f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart State state_; 133c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart ConnectionRefPtr connection_; 1343e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood base::WeakPtrFactory<HTTPProxy> weak_ptr_factory_; 1353e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood base::Callback<void(int)> accept_callback_; 1363e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood base::Callback<void(bool, int)> connect_completion_callback_; 1378ae18741780300de3126826b72593391f2d00313Paul Stewart base::Callback<void(const Error&, const IPAddress&)> dns_client_callback_; 1388ae18741780300de3126826b72593391f2d00313Paul Stewart base::Callback<void(InputData*)> read_client_callback_; 1398ae18741780300de3126826b72593391f2d00313Paul Stewart base::Callback<void(InputData*)> read_server_callback_; 1403e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood base::Callback<void(int)> write_client_callback_; 1413e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood base::Callback<void(int)> write_server_callback_; 142f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 143f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // State held while proxy is started (even if no transaction is active). 144cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<IOHandler> accept_handler_; 1458ae18741780300de3126826b72593391f2d00313Paul Stewart EventDispatcher* dispatcher_; 146cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<DNSClient> dns_client_; 147f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int proxy_port_; 148f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int proxy_socket_; 149cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<AsyncConnection> server_async_connection_; 1508ae18741780300de3126826b72593391f2d00313Paul Stewart Sockets* sockets_; 151f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 152f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart // State held while proxy is started and a transaction is active. 153f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int client_socket_; 15458a577b23de1478a72135410d146625ffd00e909Paul Stewart std::string client_method_; 155f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::string client_version_; 156f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int server_port_; 157f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart int server_socket_; 158c8f4bef3c2a277d052f96ae06e67d3e7ab44a592Paul Stewart bool is_route_requested_; 1593e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood base::CancelableClosure idle_timeout_; 160f582b50dc416de301f3e4a5f1712a93b9ce02e95Paul Stewart base::CancelableClosure transaction_timeout_; 161f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::vector<std::string> client_headers_; 162f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart std::string server_hostname_; 163f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart ByteString client_data_; 164f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart ByteString server_data_; 165cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<IOHandler> read_client_handler_; 166cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<IOHandler> write_client_handler_; 167cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<IOHandler> read_server_handler_; 168cd47732488cd101eaf0d3558dde5a7d4e4fc260bBen Chan std::unique_ptr<IOHandler> write_server_handler_; 169f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 170f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart DISALLOW_COPY_AND_ASSIGN(HTTPProxy); 171f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}; 172f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 173f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart} // namespace shill 174f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart 175c45688bb3881f0c2216e6ec0e19ebda0be33e871Ben Chan#endif // SHILL_HTTP_PROXY_H_ 176