blob: 6bc060147ebf0b1879d84e50dc90dbda48056526 [file] [log] [blame]
Paul Stewartf65320c2011-10-13 14:34:52 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// 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
53 HTTPProxy(const std::string &interface_name,
54 const std::vector<std::string> &dns_servers);
55 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
87 static const char kHTTPURLDelimiters[];
88 static const char kHTTPURLPrefix[];
89 static const char kHTTPVersionPrefix[];
90 static const char kHTTPVersionErrorMsg[];
91 static const char kInternalErrorMsg[]; // Message to send on failure.
92
93 void AcceptClient(int fd);
94 bool ConnectServer(const IPAddress &address, int port);
95 void GetDNSResult(bool result);
96 void OnConnectCompletion(bool success, int fd);
97 bool ParseClientRequest();
98 bool ProcessLastHeaderLine();
99 bool ReadClientHeaders(InputData *data);
100 bool ReadClientHostname(std::string *header);
101 bool ReadClientHTTPVersion(std::string *header);
102 void ReadFromClient(InputData *data);
103 void ReadFromServer(InputData *data);
104 void SendClientError(int code, const std::string &error);
105 void StartIdleTimeout();
106 void StartReceive();
107 void StartTransmit();
108 void StopClient();
109 void WriteToClient(int fd);
110 void WriteToServer(int fd);
111
112 // State held for the lifetime of the proxy.
113 State state_;
114 const std::string interface_name_;
115 std::vector<std::string> dns_servers_;
116 scoped_ptr<Callback1<int>::Type> accept_callback_;
117 scoped_ptr<Callback2<bool, int>::Type> connect_completion_callback_;
118 scoped_ptr<Callback1<bool>::Type> dns_client_callback_;
119 scoped_ptr<Callback1<InputData *>::Type> read_client_callback_;
120 scoped_ptr<Callback1<InputData *>::Type> read_server_callback_;
121 scoped_ptr<Callback1<int>::Type> write_client_callback_;
122 scoped_ptr<Callback1<int>::Type> write_server_callback_;
123 ScopedRunnableMethodFactory<HTTPProxy> task_factory_;
124
125 // State held while proxy is started (even if no transaction is active).
126 scoped_ptr<IOHandler> accept_handler_;
127 EventDispatcher *dispatcher_;
128 scoped_ptr<DNSClient> dns_client_;
129 int proxy_port_;
130 int proxy_socket_;
131 scoped_ptr<AsyncConnection> server_async_connection_;
132 Sockets *sockets_;
133
134 // State held while proxy is started and a transaction is active.
135 int client_socket_;
136 std::string client_version_;
137 int server_port_;
138 int server_socket_;
139 CancelableTask *idle_timeout_;
140 std::vector<std::string> client_headers_;
141 std::string server_hostname_;
142 ByteString client_data_;
143 ByteString server_data_;
144 scoped_ptr<IOHandler> read_client_handler_;
145 scoped_ptr<IOHandler> write_client_handler_;
146 scoped_ptr<IOHandler> read_server_handler_;
147 scoped_ptr<IOHandler> write_server_handler_;
148
149 DISALLOW_COPY_AND_ASSIGN(HTTPProxy);
150};
151
152} // namespace shill
153
154#endif // SHILL_HTTP_PROXY_