blob: 33032669afc3a4baa9b9265176eae1e50b8f93a0 [file] [log] [blame]
Paul Stewart58a577b2012-01-10 11:18:52 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Paul Stewartf65320c2011-10-13 14:34:52 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SHILL_HTTP_PROXY_
6#define SHILL_HTTP_PROXY_
7
8#include <string>
9#include <vector>
10
Eric Shienbrood3e20a232012-02-16 11:35:56 -050011#include <base/cancelable_callback.h>
Paul Stewartf65320c2011-10-13 14:34:52 -070012#include <base/memory/ref_counted.h>
13#include <base/memory/scoped_ptr.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050014#include <base/memory/weak_ptr.h>
Paul Stewartf65320c2011-10-13 14:34:52 -070015
16#include "shill/byte_string.h"
17#include "shill/refptr_types.h"
18
19namespace shill {
20
21class AsyncConnection;
Paul Stewartf65320c2011-10-13 14:34:52 -070022class DNSClient;
Paul Stewartbdb02e62012-02-22 16:24:33 -080023class Error;
24class EventDispatcher;
Paul Stewartf65320c2011-10-13 14:34:52 -070025class InputData;
26class IOHandler;
27class IPAddress;
28class Sockets;
29
30// The HTTPProxy class implements a simple web proxy that
31// is bound to a specific interface and name server. This
32// allows us to specify which connection a URL should be
33// fetched through, even though many connections
34// could be active at the same time.
35//
36// This service is meant to be low-performance, since we
37// do not want to divert resources from the rest of the
38// connection manager. As such, we serve one client request
39// at a time. This is probably okay since the use case is
40// limited -- only portal detection, activation and Cashew
41// are planned to be full-time users.
42class HTTPProxy {
43 public:
44 enum State {
45 kStateIdle,
46 kStateWaitConnection,
47 kStateReadClientHeader,
48 kStateLookupServer,
49 kStateConnectServer,
50 kStateTunnelData,
51 kStateFlushResponse,
52 };
53
Paul Stewartc8f4bef2011-12-13 09:45:51 -080054 explicit HTTPProxy(ConnectionRefPtr connection);
Paul Stewartf65320c2011-10-13 14:34:52 -070055 virtual ~HTTPProxy();
56
57 // Start HTTP proxy.
58 bool Start(EventDispatcher *dispatcher, Sockets *sockets);
59
60 // Shutdown.
61 void Stop();
62
63 int proxy_port() const { return proxy_port_; }
64
65 private:
66 friend class HTTPProxyTest;
67
68 // Time to wait for initial headers from client.
69 static const int kClientHeaderTimeoutSeconds;
70 // Time to wait for connection to remote server.
71 static const int kConnectTimeoutSeconds;
72 // Time to wait for DNS server.
73 static const int kDNSTimeoutSeconds;
74 // Default port on remote server to connect to.
75 static const int kDefaultServerPort;
76 // Time to wait for any input from either server or client.
77 static const int kInputTimeoutSeconds;
78 // Maximum clients to be kept waiting.
79 static const size_t kMaxClientQueue;
80 // Maximum number of header lines to accept.
81 static const size_t kMaxHeaderCount;
82 // Maximum length of an individual header line.
83 static const size_t kMaxHeaderSize;
84 // Timeout for whole transaction.
85 static const int kTransactionTimeoutSeconds;
86
Paul Stewart58a577b2012-01-10 11:18:52 -080087 static const char kHTTPMethodConnect[];
88 static const char kHTTPMethodTerminator[];
Paul Stewartf65320c2011-10-13 14:34:52 -070089 static const char kHTTPURLDelimiters[];
90 static const char kHTTPURLPrefix[];
91 static const char kHTTPVersionPrefix[];
92 static const char kHTTPVersionErrorMsg[];
93 static const char kInternalErrorMsg[]; // Message to send on failure.
94
95 void AcceptClient(int fd);
96 bool ConnectServer(const IPAddress &address, int port);
Paul Stewartbdb02e62012-02-22 16:24:33 -080097 void GetDNSResult(const Error &error, const IPAddress &address);
Paul Stewartf65320c2011-10-13 14:34:52 -070098 void OnConnectCompletion(bool success, int fd);
99 bool ParseClientRequest();
100 bool ProcessLastHeaderLine();
101 bool ReadClientHeaders(InputData *data);
102 bool ReadClientHostname(std::string *header);
Paul Stewart58a577b2012-01-10 11:18:52 -0800103 bool ReadClientHTTPMethod(std::string *header);
Paul Stewartf65320c2011-10-13 14:34:52 -0700104 bool ReadClientHTTPVersion(std::string *header);
105 void ReadFromClient(InputData *data);
106 void ReadFromServer(InputData *data);
Paul Stewart58a577b2012-01-10 11:18:52 -0800107 void SetClientResponse(int code, const std::string &type,
108 const std::string &content_type,
109 const std::string &message);
Paul Stewartf65320c2011-10-13 14:34:52 -0700110 void SendClientError(int code, const std::string &error);
111 void StartIdleTimeout();
112 void StartReceive();
113 void StartTransmit();
114 void StopClient();
115 void WriteToClient(int fd);
116 void WriteToServer(int fd);
117
118 // State held for the lifetime of the proxy.
119 State state_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800120 ConnectionRefPtr connection_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500121 base::WeakPtrFactory<HTTPProxy> weak_ptr_factory_;
122 base::Callback<void(int)> accept_callback_;
123 base::Callback<void(bool, int)> connect_completion_callback_;
124 base::Callback<void(const Error &, const IPAddress &)> dns_client_callback_;
125 base::Callback<void(InputData *)> read_client_callback_;
126 base::Callback<void(InputData *)> read_server_callback_;
127 base::Callback<void(int)> write_client_callback_;
128 base::Callback<void(int)> write_server_callback_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700129
130 // State held while proxy is started (even if no transaction is active).
131 scoped_ptr<IOHandler> accept_handler_;
132 EventDispatcher *dispatcher_;
133 scoped_ptr<DNSClient> dns_client_;
134 int proxy_port_;
135 int proxy_socket_;
136 scoped_ptr<AsyncConnection> server_async_connection_;
137 Sockets *sockets_;
138
139 // State held while proxy is started and a transaction is active.
140 int client_socket_;
Paul Stewart58a577b2012-01-10 11:18:52 -0800141 std::string client_method_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700142 std::string client_version_;
143 int server_port_;
144 int server_socket_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800145 bool is_route_requested_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500146 base::CancelableClosure idle_timeout_;
Paul Stewartf582b502012-04-04 21:39:22 -0700147 base::CancelableClosure transaction_timeout_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700148 std::vector<std::string> client_headers_;
149 std::string server_hostname_;
150 ByteString client_data_;
151 ByteString server_data_;
152 scoped_ptr<IOHandler> read_client_handler_;
153 scoped_ptr<IOHandler> write_client_handler_;
154 scoped_ptr<IOHandler> read_server_handler_;
155 scoped_ptr<IOHandler> write_server_handler_;
156
157 DISALLOW_COPY_AND_ASSIGN(HTTPProxy);
158};
159
160} // namespace shill
161
162#endif // SHILL_HTTP_PROXY_