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