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