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