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