blob: b4132c6deff59f48057c0b4f311db781cd1a5737 [file] [log] [blame]
Peter Qiuc0beca52015-09-03 11:25:46 -07001//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Paul Stewartf65320c2011-10-13 14:34:52 -070016
Ben Chanc45688b2014-07-02 23:50:45 -070017#ifndef SHILL_HTTP_PROXY_H_
18#define SHILL_HTTP_PROXY_H_
Paul Stewartf65320c2011-10-13 14:34:52 -070019
Ben Chancd477322014-10-17 14:19:30 -070020#include <memory>
Paul Stewartf65320c2011-10-13 14:34:52 -070021#include <string>
22#include <vector>
23
Eric Shienbrood3e20a232012-02-16 11:35:56 -050024#include <base/cancelable_callback.h>
Paul Stewartf65320c2011-10-13 14:34:52 -070025#include <base/memory/ref_counted.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050026#include <base/memory/weak_ptr.h>
Paul Stewartf65320c2011-10-13 14:34:52 -070027
Peter Qiu8d6b5972014-10-28 15:33:34 -070028#include "shill/net/byte_string.h"
Paul Stewartf65320c2011-10-13 14:34:52 -070029#include "shill/refptr_types.h"
30
31namespace shill {
32
33class AsyncConnection;
Paul Stewartf65320c2011-10-13 14:34:52 -070034class DNSClient;
Paul Stewartbdb02e62012-02-22 16:24:33 -080035class Error;
36class EventDispatcher;
Liam McLoughlinf4baef22012-08-01 19:08:25 -070037struct InputData;
Paul Stewartf65320c2011-10-13 14:34:52 -070038class IOHandler;
39class IPAddress;
40class Sockets;
41
42// The HTTPProxy class implements a simple web proxy that
43// is bound to a specific interface and name server. This
44// allows us to specify which connection a URL should be
45// fetched through, even though many connections
46// could be active at the same time.
47//
48// This service is meant to be low-performance, since we
49// do not want to divert resources from the rest of the
50// connection manager. As such, we serve one client request
51// at a time. This is probably okay since the use case is
52// limited -- only portal detection, activation and Cashew
53// are planned to be full-time users.
54class HTTPProxy {
55 public:
56 enum State {
57 kStateIdle,
58 kStateWaitConnection,
59 kStateReadClientHeader,
60 kStateLookupServer,
61 kStateConnectServer,
62 kStateTunnelData,
63 kStateFlushResponse,
64 };
65
Paul Stewartc8f4bef2011-12-13 09:45:51 -080066 explicit HTTPProxy(ConnectionRefPtr connection);
Paul Stewartf65320c2011-10-13 14:34:52 -070067 virtual ~HTTPProxy();
68
69 // Start HTTP proxy.
Paul Stewart8ae18742015-06-16 13:13:10 -070070 bool Start(EventDispatcher* dispatcher, Sockets* sockets);
Paul Stewartf65320c2011-10-13 14:34:52 -070071
72 // Shutdown.
73 void Stop();
74
75 int proxy_port() const { return proxy_port_; }
76
77 private:
78 friend class HTTPProxyTest;
79
80 // Time to wait for initial headers from client.
81 static const int kClientHeaderTimeoutSeconds;
82 // Time to wait for connection to remote server.
83 static const int kConnectTimeoutSeconds;
84 // Time to wait for DNS server.
85 static const int kDNSTimeoutSeconds;
86 // Default port on remote server to connect to.
87 static const int kDefaultServerPort;
88 // Time to wait for any input from either server or client.
89 static const int kInputTimeoutSeconds;
90 // Maximum clients to be kept waiting.
91 static const size_t kMaxClientQueue;
92 // Maximum number of header lines to accept.
93 static const size_t kMaxHeaderCount;
94 // Maximum length of an individual header line.
95 static const size_t kMaxHeaderSize;
96 // Timeout for whole transaction.
97 static const int kTransactionTimeoutSeconds;
98
Paul Stewart58a577b2012-01-10 11:18:52 -080099 static const char kHTTPMethodConnect[];
100 static const char kHTTPMethodTerminator[];
Paul Stewartf65320c2011-10-13 14:34:52 -0700101 static const char kHTTPURLDelimiters[];
102 static const char kHTTPURLPrefix[];
103 static const char kHTTPVersionPrefix[];
104 static const char kHTTPVersionErrorMsg[];
105 static const char kInternalErrorMsg[]; // Message to send on failure.
106
107 void AcceptClient(int fd);
Paul Stewart8ae18742015-06-16 13:13:10 -0700108 bool ConnectServer(const IPAddress& address, int port);
109 void GetDNSResult(const Error& error, const IPAddress& address);
110 void OnReadError(const std::string& error_msg);
Paul Stewartf65320c2011-10-13 14:34:52 -0700111 void OnConnectCompletion(bool success, int fd);
112 bool ParseClientRequest();
113 bool ProcessLastHeaderLine();
Paul Stewart8ae18742015-06-16 13:13:10 -0700114 bool ReadClientHeaders(InputData* data);
115 bool ReadClientHostname(std::string* header);
116 bool ReadClientHTTPMethod(std::string* header);
117 bool ReadClientHTTPVersion(std::string* header);
118 void ReadFromClient(InputData* data);
119 void ReadFromServer(InputData* data);
120 void SetClientResponse(int code, const std::string& type,
121 const std::string& content_type,
122 const std::string& message);
123 void SendClientError(int code, const std::string& error);
Paul Stewartf65320c2011-10-13 14:34:52 -0700124 void StartIdleTimeout();
125 void StartReceive();
126 void StartTransmit();
127 void StopClient();
128 void WriteToClient(int fd);
129 void WriteToServer(int fd);
130
131 // State held for the lifetime of the proxy.
132 State state_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800133 ConnectionRefPtr connection_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500134 base::WeakPtrFactory<HTTPProxy> weak_ptr_factory_;
135 base::Callback<void(int)> accept_callback_;
136 base::Callback<void(bool, int)> connect_completion_callback_;
Paul Stewart8ae18742015-06-16 13:13:10 -0700137 base::Callback<void(const Error&, const IPAddress&)> dns_client_callback_;
138 base::Callback<void(InputData*)> read_client_callback_;
139 base::Callback<void(InputData*)> read_server_callback_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500140 base::Callback<void(int)> write_client_callback_;
141 base::Callback<void(int)> write_server_callback_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700142
143 // State held while proxy is started (even if no transaction is active).
Ben Chancd477322014-10-17 14:19:30 -0700144 std::unique_ptr<IOHandler> accept_handler_;
Paul Stewart8ae18742015-06-16 13:13:10 -0700145 EventDispatcher* dispatcher_;
Ben Chancd477322014-10-17 14:19:30 -0700146 std::unique_ptr<DNSClient> dns_client_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700147 int proxy_port_;
148 int proxy_socket_;
Ben Chancd477322014-10-17 14:19:30 -0700149 std::unique_ptr<AsyncConnection> server_async_connection_;
Paul Stewart8ae18742015-06-16 13:13:10 -0700150 Sockets* sockets_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700151
152 // State held while proxy is started and a transaction is active.
153 int client_socket_;
Paul Stewart58a577b2012-01-10 11:18:52 -0800154 std::string client_method_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700155 std::string client_version_;
156 int server_port_;
157 int server_socket_;
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800158 bool is_route_requested_;
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500159 base::CancelableClosure idle_timeout_;
Paul Stewartf582b502012-04-04 21:39:22 -0700160 base::CancelableClosure transaction_timeout_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700161 std::vector<std::string> client_headers_;
162 std::string server_hostname_;
163 ByteString client_data_;
164 ByteString server_data_;
Ben Chancd477322014-10-17 14:19:30 -0700165 std::unique_ptr<IOHandler> read_client_handler_;
166 std::unique_ptr<IOHandler> write_client_handler_;
167 std::unique_ptr<IOHandler> read_server_handler_;
168 std::unique_ptr<IOHandler> write_server_handler_;
Paul Stewartf65320c2011-10-13 14:34:52 -0700169
170 DISALLOW_COPY_AND_ASSIGN(HTTPProxy);
171};
172
173} // namespace shill
174
Ben Chanc45688b2014-07-02 23:50:45 -0700175#endif // SHILL_HTTP_PROXY_H_