blob: 15419177fdfa579476458efa37c58b9b5a5bf4a5 [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
11#include <base/callback_old.h>
12#include <base/memory/ref_counted.h>
13#include <base/memory/scoped_ptr.h>
14#include <base/task.h>
15
16#include "shill/byte_string.h"
17#include "shill/refptr_types.h"
18
19namespace shill {
20
21class AsyncConnection;
22class EventDispatcher;
23class DNSClient;
24class InputData;
25class IOHandler;
26class IPAddress;
27class Sockets;
28
29// The HTTPProxy class implements a simple web proxy that
30// is bound to a specific interface and name server. This
31// allows us to specify which connection a URL should be
32// fetched through, even though many connections
33// could be active at the same time.
34//
35// This service is meant to be low-performance, since we
36// do not want to divert resources from the rest of the
37// connection manager. As such, we serve one client request
38// at a time. This is probably okay since the use case is
39// limited -- only portal detection, activation and Cashew
40// are planned to be full-time users.
41class HTTPProxy {
42 public:
43 enum State {
44 kStateIdle,
45 kStateWaitConnection,
46 kStateReadClientHeader,
47 kStateLookupServer,
48 kStateConnectServer,
49 kStateTunnelData,
50 kStateFlushResponse,
51 };
52
Paul Stewartc8f4bef2011-12-13 09:45:51 -080053 explicit HTTPProxy(ConnectionRefPtr connection);
Paul Stewartf65320c2011-10-13 14:34:52 -070054 virtual ~HTTPProxy();
55
56 // Start HTTP proxy.
57 bool Start(EventDispatcher *dispatcher, Sockets *sockets);
58
59 // Shutdown.
60 void Stop();
61
62 int proxy_port() const { return proxy_port_; }
63
64 private:
65 friend class HTTPProxyTest;
66
67 // Time to wait for initial headers from client.
68 static const int kClientHeaderTimeoutSeconds;
69 // Time to wait for connection to remote server.
70 static const int kConnectTimeoutSeconds;
71 // Time to wait for DNS server.
72 static const int kDNSTimeoutSeconds;
73 // Default port on remote server to connect to.
74 static const int kDefaultServerPort;
75 // Time to wait for any input from either server or client.
76 static const int kInputTimeoutSeconds;
77 // Maximum clients to be kept waiting.
78 static const size_t kMaxClientQueue;
79 // Maximum number of header lines to accept.
80 static const size_t kMaxHeaderCount;
81 // Maximum length of an individual header line.
82 static const size_t kMaxHeaderSize;
83 // Timeout for whole transaction.
84 static const int kTransactionTimeoutSeconds;
85
Paul Stewart58a577b2012-01-10 11:18:52 -080086 static const char kHTTPMethodConnect[];
87 static const char kHTTPMethodTerminator[];
Paul Stewartf65320c2011-10-13 14:34:52 -070088 static const char kHTTPURLDelimiters[];
89 static const char kHTTPURLPrefix[];
90 static const char kHTTPVersionPrefix[];
91 static const char kHTTPVersionErrorMsg[];
92 static const char kInternalErrorMsg[]; // Message to send on failure.
93
94 void AcceptClient(int fd);
95 bool ConnectServer(const IPAddress &address, int port);
96 void GetDNSResult(bool result);
97 void OnConnectCompletion(bool success, int fd);
98 bool ParseClientRequest();
99 bool ProcessLastHeaderLine();
100 bool ReadClientHeaders(InputData *data);
101 bool ReadClientHostname(std::string *header);
Paul Stewart58a577b2012-01-10 11:18:52 -0800102 bool ReadClientHTTPMethod(std::string *header);
Paul Stewartf65320c2011-10-13 14:34:52 -0700103 bool ReadClientHTTPVersion(std::string *header);
104 void ReadFromClient(InputData *data);
105 void ReadFromServer(InputData *data);
Paul Stewart58a577b2012-01-10 11:18:52 -0800106 void SetClientResponse(int code, const std::string &type,
107 const std::string &content_type,
108 const std::string &message);
Paul Stewartf65320c2011-10-13 14:34:52 -0700109 void SendClientError(int code, const std::string &error);
110 void StartIdleTimeout();
111 void StartReceive();
112 void StartTransmit();
113 void StopClient();
114 void WriteToClient(int fd);
115 void WriteToServer(int fd);
116
117 // State held for the lifetime of the proxy.
118 State state_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800119 ConnectionRefPtr connection_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700120 scoped_ptr<Callback1<int>::Type> accept_callback_;
121 scoped_ptr<Callback2<bool, int>::Type> connect_completion_callback_;
122 scoped_ptr<Callback1<bool>::Type> dns_client_callback_;
123 scoped_ptr<Callback1<InputData *>::Type> read_client_callback_;
124 scoped_ptr<Callback1<InputData *>::Type> read_server_callback_;
125 scoped_ptr<Callback1<int>::Type> write_client_callback_;
126 scoped_ptr<Callback1<int>::Type> write_server_callback_;
127 ScopedRunnableMethodFactory<HTTPProxy> task_factory_;
128
129 // State held while proxy is started (even if no transaction is active).
130 scoped_ptr<IOHandler> accept_handler_;
131 EventDispatcher *dispatcher_;
132 scoped_ptr<DNSClient> dns_client_;
133 int proxy_port_;
134 int proxy_socket_;
135 scoped_ptr<AsyncConnection> server_async_connection_;
136 Sockets *sockets_;
137
138 // State held while proxy is started and a transaction is active.
139 int client_socket_;
Paul Stewart58a577b2012-01-10 11:18:52 -0800140 std::string client_method_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700141 std::string client_version_;
142 int server_port_;
143 int server_socket_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800144 bool is_route_requested_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700145 CancelableTask *idle_timeout_;
146 std::vector<std::string> client_headers_;
147 std::string server_hostname_;
148 ByteString client_data_;
149 ByteString server_data_;
150 scoped_ptr<IOHandler> read_client_handler_;
151 scoped_ptr<IOHandler> write_client_handler_;
152 scoped_ptr<IOHandler> read_server_handler_;
153 scoped_ptr<IOHandler> write_server_handler_;
154
155 DISALLOW_COPY_AND_ASSIGN(HTTPProxy);
156};
157
158} // namespace shill
159
160#endif // SHILL_HTTP_PROXY_