blob: c8d2d2f5bc2b2a519a1cc1a2d02dcf5ce28e7452 [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;
Liam McLoughlinf4baef22012-08-01 19:08:25 -070025struct InputData;
Paul Stewartf65320c2011-10-13 14:34:52 -070026class 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 Stewart5f06a0e2012-12-20 11:11:33 -080098 void OnReadError(const Error &error);
Paul Stewartf65320c2011-10-13 14:34:52 -070099 void OnConnectCompletion(bool success, int fd);
100 bool ParseClientRequest();
101 bool ProcessLastHeaderLine();
102 bool ReadClientHeaders(InputData *data);
103 bool ReadClientHostname(std::string *header);
Paul Stewart58a577b2012-01-10 11:18:52 -0800104 bool ReadClientHTTPMethod(std::string *header);
Paul Stewartf65320c2011-10-13 14:34:52 -0700105 bool ReadClientHTTPVersion(std::string *header);
106 void ReadFromClient(InputData *data);
107 void ReadFromServer(InputData *data);
Paul Stewart58a577b2012-01-10 11:18:52 -0800108 void SetClientResponse(int code, const std::string &type,
109 const std::string &content_type,
110 const std::string &message);
Paul Stewartf65320c2011-10-13 14:34:52 -0700111 void SendClientError(int code, const std::string &error);
112 void StartIdleTimeout();
113 void StartReceive();
114 void StartTransmit();
115 void StopClient();
116 void WriteToClient(int fd);
117 void WriteToServer(int fd);
118
119 // State held for the lifetime of the proxy.
120 State state_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800121 ConnectionRefPtr connection_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500122 base::WeakPtrFactory<HTTPProxy> weak_ptr_factory_;
123 base::Callback<void(int)> accept_callback_;
124 base::Callback<void(bool, int)> connect_completion_callback_;
125 base::Callback<void(const Error &, const IPAddress &)> dns_client_callback_;
126 base::Callback<void(InputData *)> read_client_callback_;
127 base::Callback<void(InputData *)> read_server_callback_;
128 base::Callback<void(int)> write_client_callback_;
129 base::Callback<void(int)> write_server_callback_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700130
131 // State held while proxy is started (even if no transaction is active).
132 scoped_ptr<IOHandler> accept_handler_;
133 EventDispatcher *dispatcher_;
134 scoped_ptr<DNSClient> dns_client_;
135 int proxy_port_;
136 int proxy_socket_;
137 scoped_ptr<AsyncConnection> server_async_connection_;
138 Sockets *sockets_;
139
140 // State held while proxy is started and a transaction is active.
141 int client_socket_;
Paul Stewart58a577b2012-01-10 11:18:52 -0800142 std::string client_method_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700143 std::string client_version_;
144 int server_port_;
145 int server_socket_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800146 bool is_route_requested_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500147 base::CancelableClosure idle_timeout_;
Paul Stewartf582b502012-04-04 21:39:22 -0700148 base::CancelableClosure transaction_timeout_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700149 std::vector<std::string> client_headers_;
150 std::string server_hostname_;
151 ByteString client_data_;
152 ByteString server_data_;
153 scoped_ptr<IOHandler> read_client_handler_;
154 scoped_ptr<IOHandler> write_client_handler_;
155 scoped_ptr<IOHandler> read_server_handler_;
156 scoped_ptr<IOHandler> write_server_handler_;
157
158 DISALLOW_COPY_AND_ASSIGN(HTTPProxy);
159};
160
161} // namespace shill
162
163#endif // SHILL_HTTP_PROXY_