1 //
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 //
16
17 #include "shill/http_proxy.h"
18
19 #include <netinet/in.h>
20
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 #include <base/strings/stringprintf.h>
26 #include <gtest/gtest.h>
27
28 #include "shill/mock_async_connection.h"
29 #include "shill/mock_connection.h"
30 #include "shill/mock_control.h"
31 #include "shill/mock_device_info.h"
32 #include "shill/mock_dns_client.h"
33 #include "shill/mock_event_dispatcher.h"
34 #include "shill/net/ip_address.h"
35 #include "shill/net/mock_sockets.h"
36
37 using base::StringPrintf;
38 using std::string;
39 using std::vector;
40 using ::testing::_;
41 using ::testing::AnyNumber;
42 using ::testing::AtLeast;
43 using ::testing::DoAll;
44 using ::testing::Invoke;
45 using ::testing::NiceMock;
46 using ::testing::Return;
47 using ::testing::ReturnArg;
48 using ::testing::ReturnNew;
49 using ::testing::ReturnRef;
50 using ::testing::SetArgumentPointee;
51 using ::testing::StrEq;
52 using ::testing::StrictMock;
53 using ::testing::Test;
54
55 namespace shill {
56
57 namespace {
58 const char kBadHeaderMissingURL[] = "BLAH\r\n";
59 const char kBadHeaderMissingVersion[] = "BLAH http://hostname\r\n";
60 const char kBadHostnameLine[] = "GET HTTP/1.1 http://hostname\r\n";
61 const char kBasicGetHeader[] = "GET / HTTP/1.1\r\n";
62 const char kBasicGetHeaderWithURL[] =
63 "GET http://www.chromium.org/ HTTP/1.1\r\n";
64 const char kBasicGetHeaderWithURLNoTrailingSlash[] =
65 "GET http://www.chromium.org HTTP/1.1\r\n";
66 const char kConnectQuery[] =
67 "CONNECT 10.10.10.10:443 HTTP/1.1\r\n"
68 "Host: 10.10.10.10:443\r\n\r\n";
69 const char kQueryTemplate[] = "GET %s HTTP/%s\r\n%s"
70 "User-Agent: Mozilla/5.0 (X11; CrOS i686 1299.0.2011) "
71 "AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.936.0 Safari/535.8\r\n"
72 "Accept: text/html,application/xhtml+xml,application/xml;"
73 "q=0.9,*/*;q=0.8\r\n"
74 "Accept-Encoding: gzip,deflate,sdch\r\n"
75 "Accept-Language: en-US,en;q=0.8,ja;q=0.6\r\n"
76 "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n"
77 "Cookie: PREF=ID=xxxxxxxxxxxxxxxx:U=xxxxxxxxxxxxxxxx:FF=0:"
78 "TM=1317340083:LM=1317390705:GM=1:S=_xxxxxxxxxxxxxxx; "
79 "NID=52=xxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
80 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxx; "
81 "HSID=xxxxxxxxxxxx-xxxx; APISID=xxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxx; "
82 "SID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxx"
83 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx"
84 "xxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxx"
85 "_xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx-xx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
86 "xxxxxxxxxxxxxxxx\r\n\r\n";
87 const char kInterfaceName[] = "int0";
88 const char kDNSServer0[] = "8.8.8.8";
89 const char kDNSServer1[] = "8.8.4.4";
90 const char kServerAddress[] = "10.10.10.10";
91 const char* kDNSServers[] = { kDNSServer0, kDNSServer1 };
92 const int kProxyFD = 10203;
93 const int kServerFD = 10204;
94 const int kClientFD = 10205;
95 const int kServerPort = 40506;
96 const int kConnectPort = 443;
97 } // namespace
98
99 MATCHER_P(IsIPAddress, address, "") {
100 IPAddress ip_address(IPAddress::kFamilyIPv4);
101 EXPECT_TRUE(ip_address.SetAddressFromString(address));
102 return ip_address.Equals(arg);
103 }
104
105 MATCHER_P(CallbackEq, callback, "") {
106 return arg.Equals(callback);
107 }
108
109 class HTTPProxyTest : public Test {
110 public:
HTTPProxyTest()111 HTTPProxyTest()
112 : interface_name_(kInterfaceName),
113 server_async_connection_(nullptr),
114 dns_servers_(kDNSServers, kDNSServers + 2),
115 dns_client_(nullptr),
116 device_info_(
117 new NiceMock<MockDeviceInfo>(&control_, nullptr, nullptr, nullptr)),
118 connection_(new StrictMock<MockConnection>(device_info_.get())),
119 proxy_(connection_) {}
120
121 protected:
SetUp()122 virtual void SetUp() {
123 EXPECT_CALL(*connection_.get(), interface_name())
124 .WillRepeatedly(ReturnRef(interface_name_));
125 EXPECT_CALL(*connection_.get(), dns_servers())
126 .WillRepeatedly(ReturnRef(dns_servers_));
127 }
TearDown()128 virtual void TearDown() {
129 if (proxy_.sockets_) {
130 ExpectStop();
131 }
132 const int proxy_fds[] = {
133 proxy_.client_socket_,
134 proxy_.server_socket_,
135 proxy_.proxy_socket_
136 };
137 for (const int fd : proxy_fds) {
138 if (fd != -1) {
139 EXPECT_CALL(sockets_, Close(fd));
140 }
141 }
142 }
CreateRequest(const string & url,const string & http_version,const string & extra_lines)143 string CreateRequest(const string& url, const string& http_version,
144 const string& extra_lines) {
145 string append_lines(extra_lines);
146 if (append_lines.size()) {
147 append_lines.append("\r\n");
148 }
149 return StringPrintf(kQueryTemplate, url.c_str(), http_version.c_str(),
150 append_lines.c_str());
151 }
InvokeGetSockName(int fd,struct sockaddr * addr_out,socklen_t * sockaddr_size)152 int InvokeGetSockName(int fd, struct sockaddr* addr_out,
153 socklen_t* sockaddr_size) {
154 struct sockaddr_in addr;
155 EXPECT_EQ(kProxyFD, fd);
156 EXPECT_GE(sizeof(sockaddr_in), *sockaddr_size);
157 addr.sin_addr.s_addr = 0;
158 addr.sin_port = kServerPort;
159 memcpy(addr_out, &addr, sizeof(addr));
160 *sockaddr_size = sizeof(sockaddr_in);
161 return 0;
162 }
InvokeSyncConnect(const IPAddress &,int)163 void InvokeSyncConnect(const IPAddress& /*address*/, int /*port*/) {
164 proxy_.OnConnectCompletion(true, kServerFD);
165 }
FindInRequest(const string & find_string)166 size_t FindInRequest(const string& find_string) {
167 const ByteString& request_data = GetClientData();
168 string request_string(
169 reinterpret_cast<const char*>(request_data.GetConstData()),
170 request_data.GetLength());
171 return request_string.find(find_string);
172 }
173 // Accessors
GetClientData()174 const ByteString& GetClientData() {
175 return proxy_.client_data_;
176 }
proxy()177 HTTPProxy* proxy() { return &proxy_; }
GetProxyState()178 HTTPProxy::State GetProxyState() {
179 return proxy_.state_;
180 }
GetServerData()181 const ByteString& GetServerData() {
182 return proxy_.server_data_;
183 }
sockets()184 MockSockets& sockets() { return sockets_; }
dispatcher()185 MockEventDispatcher& dispatcher() { return dispatcher_; }
186
187
188 // Expectations
ExpectClientReset()189 void ExpectClientReset() {
190 EXPECT_EQ(-1, proxy_.client_socket_);
191 EXPECT_TRUE(proxy_.client_version_.empty());
192 EXPECT_EQ(HTTPProxy::kDefaultServerPort, proxy_.server_port_);
193 EXPECT_EQ(-1, proxy_.server_socket_);
194 EXPECT_TRUE(proxy_.idle_timeout_.IsCancelled());
195 EXPECT_TRUE(proxy_.client_headers_.empty());
196 EXPECT_TRUE(proxy_.server_hostname_.empty());
197 EXPECT_TRUE(proxy_.client_data_.IsEmpty());
198 EXPECT_TRUE(proxy_.server_data_.IsEmpty());
199 EXPECT_FALSE(proxy_.read_client_handler_.get());
200 EXPECT_FALSE(proxy_.write_client_handler_.get());
201 EXPECT_FALSE(proxy_.read_server_handler_.get());
202 EXPECT_FALSE(proxy_.write_server_handler_.get());
203 EXPECT_FALSE(proxy_.is_route_requested_);
204 }
ExpectReset()205 void ExpectReset() {
206 EXPECT_FALSE(proxy_.accept_handler_.get());
207 EXPECT_EQ(proxy_.connection_.get(), connection_.get());
208 EXPECT_FALSE(proxy_.dispatcher_);
209 EXPECT_FALSE(proxy_.dns_client_.get());
210 EXPECT_EQ(-1, proxy_.proxy_port_);
211 EXPECT_EQ(-1, proxy_.proxy_socket_);
212 EXPECT_FALSE(proxy_.server_async_connection_.get());
213 EXPECT_FALSE(proxy_.sockets_);
214 EXPECT_EQ(HTTPProxy::kStateIdle, proxy_.state_);
215 ExpectClientReset();
216 }
ExpectStart()217 void ExpectStart() {
218 EXPECT_CALL(sockets(), Socket(_, _, _))
219 .WillOnce(Return(kProxyFD));
220 EXPECT_CALL(sockets(), Bind(kProxyFD, _, _))
221 .WillOnce(Return(0));
222 EXPECT_CALL(sockets(), GetSockName(kProxyFD, _, _))
223 .WillOnce(Invoke(this, &HTTPProxyTest::InvokeGetSockName));
224 EXPECT_CALL(sockets(), SetNonBlocking(kProxyFD))
225 .WillOnce(Return(0));
226 EXPECT_CALL(sockets(), Listen(kProxyFD, _))
227 .WillOnce(Return(0));
228 EXPECT_CALL(dispatcher_,
229 CreateReadyHandler(kProxyFD,
230 IOHandler::kModeInput,
231 CallbackEq(proxy_.accept_callback_)))
232 .WillOnce(ReturnNew<IOHandler>());
233 }
ExpectStop()234 void ExpectStop() {
235 if (dns_client_) {
236 EXPECT_CALL(*dns_client_, Stop())
237 .Times(AtLeast(1));
238 }
239 if (server_async_connection_) {
240 EXPECT_CALL(*server_async_connection_, Stop())
241 .Times(AtLeast(1));
242 }
243 if (proxy_.is_route_requested_) {
244 EXPECT_CALL(*connection_.get(), ReleaseRouting());
245 }
246 }
ExpectClientInput(int fd)247 void ExpectClientInput(int fd) {
248 EXPECT_CALL(sockets(), Accept(kProxyFD, _, _))
249 .WillOnce(Return(fd));
250 EXPECT_CALL(sockets(), SetNonBlocking(fd))
251 .WillOnce(Return(0));
252 EXPECT_CALL(dispatcher(),
253 CreateInputHandler(fd,
254 CallbackEq(proxy_.read_client_callback_), _))
255 .WillOnce(ReturnNew<IOHandler>());
256 ExpectTransactionTimeout();
257 ExpectClientHeaderTimeout();
258 }
ExpectTimeout(int timeout)259 void ExpectTimeout(int timeout) {
260 EXPECT_CALL(dispatcher_, PostDelayedTask(_, timeout * 1000));
261 }
ExpectClientHeaderTimeout()262 void ExpectClientHeaderTimeout() {
263 ExpectTimeout(HTTPProxy::kClientHeaderTimeoutSeconds);
264 }
ExpectConnectTimeout()265 void ExpectConnectTimeout() {
266 ExpectTimeout(HTTPProxy::kConnectTimeoutSeconds);
267 }
ExpectInputTimeout()268 void ExpectInputTimeout() {
269 ExpectTimeout(HTTPProxy::kInputTimeoutSeconds);
270 }
ExpectRepeatedInputTimeout()271 void ExpectRepeatedInputTimeout() {
272 EXPECT_CALL(dispatcher_,
273 PostDelayedTask(_, HTTPProxy::kInputTimeoutSeconds * 1000))
274 .Times(AnyNumber());
275 }
ExpectTransactionTimeout()276 void ExpectTransactionTimeout() {
277 ExpectTimeout(HTTPProxy::kTransactionTimeoutSeconds);
278 }
ExpectInClientResponse(const string & response_data)279 void ExpectInClientResponse(const string& response_data) {
280 string server_data(reinterpret_cast<char*>(proxy_.server_data_.GetData()),
281 proxy_.server_data_.GetLength());
282 EXPECT_NE(string::npos, server_data.find(response_data));
283 }
ExpectClientError(int code,const string & error)284 void ExpectClientError(int code, const string& error) {
285 EXPECT_EQ(HTTPProxy::kStateFlushResponse, GetProxyState());
286 string status_line = StringPrintf("HTTP/1.1 %d ERROR", code);
287 ExpectInClientResponse(status_line);
288 ExpectInClientResponse(error);
289 }
ExpectClientInternalError()290 void ExpectClientInternalError() {
291 ExpectClientError(500, HTTPProxy::kInternalErrorMsg);
292 }
ExpectClientVersion(const string & version)293 void ExpectClientVersion(const string& version) {
294 EXPECT_EQ(version, proxy_.client_version_);
295 }
ExpectServerHostname(const string & hostname)296 void ExpectServerHostname(const string& hostname) {
297 EXPECT_EQ(hostname, proxy_.server_hostname_);
298 }
ExpectFirstLine(const string & line)299 void ExpectFirstLine(const string& line) {
300 EXPECT_EQ(line, proxy_.client_headers_[0] + "\r\n");
301 }
ExpectDNSRequest(const string & host,bool return_value)302 void ExpectDNSRequest(const string& host, bool return_value) {
303 EXPECT_CALL(*dns_client_, Start(StrEq(host), _))
304 .WillOnce(Return(return_value));
305 }
ExpectAsyncConnect(const string & address,int port,bool return_value)306 void ExpectAsyncConnect(const string& address, int port,
307 bool return_value) {
308 EXPECT_CALL(*server_async_connection_, Start(IsIPAddress(address), port))
309 .WillOnce(Return(return_value));
310 }
ExpectSyncConnect(const string & address,int port)311 void ExpectSyncConnect(const string& address, int port) {
312 EXPECT_CALL(*server_async_connection_, Start(IsIPAddress(address), port))
313 .WillOnce(DoAll(Invoke(this, &HTTPProxyTest::InvokeSyncConnect),
314 Return(true)));
315 }
ExpectClientData()316 void ExpectClientData() {
317 EXPECT_CALL(dispatcher(),
318 CreateReadyHandler(kClientFD,
319 IOHandler::kModeOutput,
320 CallbackEq(proxy_.write_client_callback_)))
321 .WillOnce(ReturnNew<IOHandler>());
322 }
ExpectClientResult()323 void ExpectClientResult() {
324 ExpectClientData();
325 ExpectInputTimeout();
326 }
ExpectServerInput()327 void ExpectServerInput() {
328 EXPECT_CALL(dispatcher(),
329 CreateInputHandler(kServerFD,
330 CallbackEq(proxy_.read_server_callback_), _))
331 .WillOnce(ReturnNew<IOHandler>());
332 ExpectInputTimeout();
333 }
ExpectServerOutput()334 void ExpectServerOutput() {
335 EXPECT_CALL(dispatcher(),
336 CreateReadyHandler(kServerFD,
337 IOHandler::kModeOutput,
338 CallbackEq(proxy_.write_server_callback_)))
339 .WillOnce(ReturnNew<IOHandler>());
340 ExpectInputTimeout();
341 }
ExpectRepeatedServerOutput()342 void ExpectRepeatedServerOutput() {
343 EXPECT_CALL(dispatcher(),
344 CreateReadyHandler(kServerFD, IOHandler::kModeOutput,
345 CallbackEq(proxy_.write_server_callback_)))
346 .WillOnce(ReturnNew<IOHandler>());
347 ExpectRepeatedInputTimeout();
348 }
ExpectTunnelClose()349 void ExpectTunnelClose() {
350 EXPECT_CALL(sockets(), Close(kClientFD))
351 .WillOnce(Return(0));
352 EXPECT_CALL(sockets(), Close(kServerFD))
353 .WillOnce(Return(0));
354 ExpectStop();
355 }
ExpectRouteRequest()356 void ExpectRouteRequest() {
357 EXPECT_CALL(*connection_.get(), RequestRouting());
358 }
ExpectRouteRelease()359 void ExpectRouteRelease() {
360 EXPECT_CALL(*connection_.get(), ReleaseRouting());
361 }
362
363 // Callers for various private routines in the proxy
StartProxy()364 bool StartProxy() {
365 bool ret = proxy_.Start(&dispatcher_, &sockets_);
366 if (ret) {
367 dns_client_ = new StrictMock<MockDNSClient>();
368 // Passes ownership.
369 proxy_.dns_client_.reset(dns_client_);
370 server_async_connection_ = new StrictMock<MockAsyncConnection>();
371 // Passes ownership.
372 proxy_.server_async_connection_.reset(server_async_connection_);
373 }
374 return ret;
375 }
AcceptClient(int fd)376 void AcceptClient(int fd) {
377 proxy_.AcceptClient(fd);
378 }
GetDNSResultFailure(const string & error_msg)379 void GetDNSResultFailure(const string& error_msg) {
380 Error error(Error::kOperationFailed, error_msg);
381 IPAddress address(IPAddress::kFamilyUnknown);
382 proxy_.GetDNSResult(error, address);
383 }
GetDNSResultSuccess(const IPAddress & address)384 void GetDNSResultSuccess(const IPAddress& address) {
385 Error error;
386 proxy_.GetDNSResult(error, address);
387 }
OnConnectCompletion(bool result,int sockfd)388 void OnConnectCompletion(bool result, int sockfd) {
389 proxy_.OnConnectCompletion(result, sockfd);
390 }
ReadFromClient(const string & data)391 void ReadFromClient(const string& data) {
392 const unsigned char* ptr =
393 reinterpret_cast<const unsigned char*>(data.c_str());
394 vector<unsigned char> data_bytes(ptr, ptr + data.length());
395 InputData proxy_data(data_bytes.data(), data_bytes.size());
396 proxy_.ReadFromClient(&proxy_data);
397 }
ReadFromServer(const string & data)398 void ReadFromServer(const string& data) {
399 const unsigned char* ptr =
400 reinterpret_cast<const unsigned char*>(data.c_str());
401 vector<unsigned char> data_bytes(ptr, ptr + data.length());
402 InputData proxy_data(data_bytes.data(), data_bytes.size());
403 proxy_.ReadFromServer(&proxy_data);
404 }
SendClientError(int code,const string & error)405 void SendClientError(int code, const string& error) {
406 proxy_.SendClientError(code, error);
407 EXPECT_FALSE(proxy_.server_data_.IsEmpty());
408 }
StopClient()409 void StopClient() {
410 EXPECT_CALL(*dns_client_, Stop());
411 EXPECT_CALL(*server_async_connection_, Stop());
412 proxy_.StopClient();
413 }
StopProxy()414 void StopProxy() {
415 ExpectStop();
416 proxy_.Stop();
417 server_async_connection_ = nullptr;
418 dns_client_ = nullptr;
419 ExpectReset();
420 }
WriteToClient(int fd)421 void WriteToClient(int fd) {
422 proxy_.WriteToClient(fd);
423 }
WriteToServer(int fd)424 void WriteToServer(int fd) {
425 proxy_.WriteToServer(fd);
426 }
427
SetupClient()428 void SetupClient() {
429 ExpectStart();
430 ASSERT_TRUE(StartProxy());
431 ExpectClientInput(kClientFD);
432 AcceptClient(kProxyFD);
433 EXPECT_EQ(HTTPProxy::kStateReadClientHeader, GetProxyState());
434 }
SetupConnectWithRequest(const string & url,const string & http_version,const string & extra_lines)435 void SetupConnectWithRequest(const string& url, const string& http_version,
436 const string& extra_lines) {
437 ExpectDNSRequest("www.chromium.org", true);
438 ExpectRouteRequest();
439 ReadFromClient(CreateRequest(url, http_version, extra_lines));
440 IPAddress addr(IPAddress::kFamilyIPv4);
441 EXPECT_TRUE(addr.SetAddressFromString(kServerAddress));
442 GetDNSResultSuccess(addr);
443 }
SetupConnect()444 void SetupConnect() {
445 SetupConnectWithRequest("/", "1.1", "Host: www.chromium.org:40506");
446 }
SetupConnectAsync()447 void SetupConnectAsync() {
448 SetupClient();
449 ExpectAsyncConnect(kServerAddress, kServerPort, true);
450 ExpectConnectTimeout();
451 SetupConnect();
452 }
SetupConnectComplete()453 void SetupConnectComplete() {
454 SetupConnectAsync();
455 ExpectServerOutput();
456 OnConnectCompletion(true, kServerFD);
457 EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState());
458 }
CauseReadError()459 void CauseReadError() {
460 proxy_.OnReadError(string());
461 }
462
463 private:
464 const string interface_name_;
465 // Owned by the HTTPProxy, but tracked here for EXPECT().
466 StrictMock<MockAsyncConnection>* server_async_connection_;
467 vector<string> dns_servers_;
468 // Owned by the HTTPProxy, but tracked here for EXPECT().
469 StrictMock<MockDNSClient>* dns_client_;
470 MockEventDispatcher dispatcher_;
471 MockControl control_;
472 std::unique_ptr<MockDeviceInfo> device_info_;
473 scoped_refptr<MockConnection> connection_;
474 StrictMock<MockSockets> sockets_;
475 HTTPProxy proxy_; // Destroy first, before anything it references.
476 };
477
TEST_F(HTTPProxyTest,StartFailSocket)478 TEST_F(HTTPProxyTest, StartFailSocket) {
479 EXPECT_CALL(sockets(), Socket(_, _, _))
480 .WillOnce(Return(-1));
481 EXPECT_FALSE(StartProxy());
482 ExpectReset();
483 }
484
TEST_F(HTTPProxyTest,StartFailBind)485 TEST_F(HTTPProxyTest, StartFailBind) {
486 EXPECT_CALL(sockets(), Socket(_, _, _))
487 .WillOnce(Return(kProxyFD));
488 EXPECT_CALL(sockets(), Bind(kProxyFD, _, _))
489 .WillOnce(Return(-1));
490 EXPECT_CALL(sockets(), Close(kProxyFD))
491 .WillOnce(Return(0));
492 EXPECT_FALSE(StartProxy());
493 ExpectReset();
494 }
495
TEST_F(HTTPProxyTest,StartFailGetSockName)496 TEST_F(HTTPProxyTest, StartFailGetSockName) {
497 EXPECT_CALL(sockets(), Socket(_, _, _))
498 .WillOnce(Return(kProxyFD));
499 EXPECT_CALL(sockets(), Bind(kProxyFD, _, _))
500 .WillOnce(Return(0));
501 EXPECT_CALL(sockets(), GetSockName(kProxyFD, _, _))
502 .WillOnce(Return(-1));
503 EXPECT_CALL(sockets(), Close(kProxyFD))
504 .WillOnce(Return(0));
505 EXPECT_FALSE(StartProxy());
506 ExpectReset();
507 }
508
TEST_F(HTTPProxyTest,StartFailSetNonBlocking)509 TEST_F(HTTPProxyTest, StartFailSetNonBlocking) {
510 EXPECT_CALL(sockets(), Socket(_, _, _))
511 .WillOnce(Return(kProxyFD));
512 EXPECT_CALL(sockets(), Bind(kProxyFD, _, _))
513 .WillOnce(Return(0));
514 EXPECT_CALL(sockets(), GetSockName(kProxyFD, _, _))
515 .WillOnce(Return(0));
516 EXPECT_CALL(sockets(), SetNonBlocking(kProxyFD))
517 .WillOnce(Return(-1));
518 EXPECT_CALL(sockets(), Close(kProxyFD))
519 .WillOnce(Return(0));
520 EXPECT_FALSE(StartProxy());
521 ExpectReset();
522 }
523
TEST_F(HTTPProxyTest,StartFailListen)524 TEST_F(HTTPProxyTest, StartFailListen) {
525 EXPECT_CALL(sockets(), Socket(_, _, _))
526 .WillOnce(Return(kProxyFD));
527 EXPECT_CALL(sockets(), Bind(kProxyFD, _, _))
528 .WillOnce(Return(0));
529 EXPECT_CALL(sockets(), GetSockName(kProxyFD, _, _))
530 .WillOnce(Return(0));
531 EXPECT_CALL(sockets(), SetNonBlocking(kProxyFD))
532 .WillOnce(Return(0));
533 EXPECT_CALL(sockets(), Listen(kProxyFD, _))
534 .WillOnce(Return(-1));
535 EXPECT_CALL(sockets(), Close(kProxyFD))
536 .WillOnce(Return(0));
537 EXPECT_FALSE(StartProxy());
538 ExpectReset();
539 }
540
TEST_F(HTTPProxyTest,StartSuccess)541 TEST_F(HTTPProxyTest, StartSuccess) {
542 ExpectStart();
543 EXPECT_TRUE(StartProxy());
544 }
545
TEST_F(HTTPProxyTest,SendClientError)546 TEST_F(HTTPProxyTest, SendClientError) {
547 SetupClient();
548 ExpectClientResult();
549 SendClientError(500, "This is an error");
550 ExpectClientError(500, "This is an error");
551
552 // We succeed in sending all but one byte of the client response.
553 int buf_len = GetServerData().GetLength();
554 EXPECT_CALL(sockets(), Send(kClientFD, _, buf_len, 0))
555 .WillOnce(Return(buf_len - 1));
556 ExpectInputTimeout();
557 WriteToClient(kClientFD);
558 EXPECT_EQ(1, GetServerData().GetLength());
559 EXPECT_EQ(HTTPProxy::kStateFlushResponse, GetProxyState());
560
561 // When we are able to send the last byte, we close the connection.
562 EXPECT_CALL(sockets(), Send(kClientFD, _, 1, 0))
563 .WillOnce(Return(1));
564 EXPECT_CALL(sockets(), Close(kClientFD))
565 .WillOnce(Return(0));
566 ExpectStop();
567 WriteToClient(kClientFD);
568 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
569 }
570
TEST_F(HTTPProxyTest,ReadMissingURL)571 TEST_F(HTTPProxyTest, ReadMissingURL) {
572 SetupClient();
573 ExpectClientResult();
574 ReadFromClient(kBadHeaderMissingURL);
575 ExpectClientError(501, "Server could not parse HTTP method");
576 }
577
TEST_F(HTTPProxyTest,ReadMissingVersion)578 TEST_F(HTTPProxyTest, ReadMissingVersion) {
579 SetupClient();
580 ExpectClientResult();
581 ReadFromClient(kBadHeaderMissingVersion);
582 ExpectClientError(501, "Server only accepts HTTP/1.x requests");
583 }
584
TEST_F(HTTPProxyTest,ReadBadHostname)585 TEST_F(HTTPProxyTest, ReadBadHostname) {
586 SetupClient();
587 ExpectClientResult();
588 ReadFromClient(kBadHostnameLine);
589 ExpectClientInternalError();
590 }
591
TEST_F(HTTPProxyTest,GoodFirstLineWithoutURL)592 TEST_F(HTTPProxyTest, GoodFirstLineWithoutURL) {
593 SetupClient();
594 ExpectClientHeaderTimeout();
595 ReadFromClient(kBasicGetHeader);
596 ExpectClientVersion("1.1");
597 ExpectServerHostname("");
598 ExpectFirstLine(kBasicGetHeader);
599 }
600
TEST_F(HTTPProxyTest,GoodFirstLineWithURL)601 TEST_F(HTTPProxyTest, GoodFirstLineWithURL) {
602 SetupClient();
603 ExpectClientHeaderTimeout();
604 ReadFromClient(kBasicGetHeaderWithURL);
605 ExpectClientVersion("1.1");
606 ExpectServerHostname("www.chromium.org");
607 ExpectFirstLine(kBasicGetHeader);
608 }
609
TEST_F(HTTPProxyTest,GoodFirstLineWithURLNoSlash)610 TEST_F(HTTPProxyTest, GoodFirstLineWithURLNoSlash) {
611 SetupClient();
612 ExpectClientHeaderTimeout();
613 ReadFromClient(kBasicGetHeaderWithURLNoTrailingSlash);
614 ExpectClientVersion("1.1");
615 ExpectServerHostname("www.chromium.org");
616 ExpectFirstLine(kBasicGetHeader);
617 }
618
TEST_F(HTTPProxyTest,NoHostInRequest)619 TEST_F(HTTPProxyTest, NoHostInRequest) {
620 SetupClient();
621 ExpectClientResult();
622 ReadFromClient(CreateRequest("/", "1.1", ""));
623 ExpectClientError(400, "I don't know what host you want me to connect to");
624 }
625
TEST_F(HTTPProxyTest,TooManyColonsInHost)626 TEST_F(HTTPProxyTest, TooManyColonsInHost) {
627 SetupClient();
628 ExpectClientResult();
629 ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:80:40506"));
630 ExpectClientError(400, "Too many colons in hostname");
631 }
632
TEST_F(HTTPProxyTest,ClientReadError)633 TEST_F(HTTPProxyTest, ClientReadError) {
634 SetupClient();
635 EXPECT_CALL(sockets(), Close(kClientFD))
636 .WillOnce(Return(0));
637 ExpectStop();
638 CauseReadError();
639 ExpectClientReset();
640 }
641
TEST_F(HTTPProxyTest,DNSRequestFailure)642 TEST_F(HTTPProxyTest, DNSRequestFailure) {
643 SetupClient();
644 ExpectRouteRequest();
645 ExpectDNSRequest("www.chromium.org", false);
646 ExpectClientResult();
647 ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:40506"));
648 ExpectClientError(502, "Could not resolve hostname");
649 }
650
TEST_F(HTTPProxyTest,DNSRequestDelayedFailure)651 TEST_F(HTTPProxyTest, DNSRequestDelayedFailure) {
652 SetupClient();
653 ExpectRouteRequest();
654 ExpectDNSRequest("www.chromium.org", true);
655 ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:40506"));
656 ExpectClientResult();
657 const std::string not_found_error(DNSClient::kErrorNotFound);
658 GetDNSResultFailure(not_found_error);
659 ExpectClientError(502, string("Could not resolve hostname: ") +
660 not_found_error);
661 }
662
TEST_F(HTTPProxyTest,TrailingClientData)663 TEST_F(HTTPProxyTest, TrailingClientData) {
664 SetupClient();
665 ExpectRouteRequest();
666 ExpectDNSRequest("www.chromium.org", true);
667 const string trailing_data("Trailing client data");
668 ReadFromClient(CreateRequest("/", "1.1", "Host: www.chromium.org:40506") +
669 trailing_data);
670 EXPECT_EQ(GetClientData().GetLength() - trailing_data.length(),
671 FindInRequest(trailing_data));
672 EXPECT_EQ(HTTPProxy::kStateLookupServer, GetProxyState());
673 }
674
TEST_F(HTTPProxyTest,LineContinuation)675 TEST_F(HTTPProxyTest, LineContinuation) {
676 SetupClient();
677 ExpectRouteRequest();
678 ExpectDNSRequest("www.chromium.org", true);
679 string text_to_keep("X-Long-Header: this is one line\r\n"
680 "\tand this is another");
681 ReadFromClient(CreateRequest("http://www.chromium.org/", "1.1",
682 text_to_keep));
683 EXPECT_NE(string::npos, FindInRequest(text_to_keep));
684 }
685
686 // NB: This tests two different things:
687 // 1) That the system replaces the value for "Proxy-Connection" headers.
688 // 2) That when it replaces a header, it also removes the text in the line
689 // continuation.
TEST_F(HTTPProxyTest,LineContinuationRemoval)690 TEST_F(HTTPProxyTest, LineContinuationRemoval) {
691 SetupClient();
692 ExpectRouteRequest();
693 ExpectDNSRequest("www.chromium.org", true);
694 string text_to_remove("remove this text please");
695 ReadFromClient(CreateRequest("http://www.chromium.org/", "1.1",
696 string("Proxy-Connection: stuff\r\n\t") +
697 text_to_remove));
698 EXPECT_EQ(string::npos, FindInRequest(text_to_remove));
699 EXPECT_NE(string::npos, FindInRequest("Proxy-Connection: close\r\n"));
700 }
701
TEST_F(HTTPProxyTest,ConnectSynchronousFailure)702 TEST_F(HTTPProxyTest, ConnectSynchronousFailure) {
703 SetupClient();
704 ExpectAsyncConnect(kServerAddress, kServerPort, false);
705 ExpectClientResult();
706 SetupConnect();
707 ExpectClientError(500, "Could not create socket to connect to server");
708 }
709
TEST_F(HTTPProxyTest,ConnectAsyncConnectFailure)710 TEST_F(HTTPProxyTest, ConnectAsyncConnectFailure) {
711 SetupConnectAsync();
712 ExpectClientResult();
713 OnConnectCompletion(false, -1);
714 ExpectClientError(500, "Socket connection delayed failure");
715 }
716
TEST_F(HTTPProxyTest,ConnectSynchronousSuccess)717 TEST_F(HTTPProxyTest, ConnectSynchronousSuccess) {
718 SetupClient();
719 ExpectSyncConnect(kServerAddress, 999);
720 ExpectRepeatedServerOutput();
721 SetupConnectWithRequest("/", "1.1", "Host: www.chromium.org:999");
722 EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState());
723 }
724
TEST_F(HTTPProxyTest,ConnectIPAddresss)725 TEST_F(HTTPProxyTest, ConnectIPAddresss) {
726 SetupClient();
727 ExpectSyncConnect(kServerAddress, 999);
728 ExpectRepeatedServerOutput();
729 ExpectRouteRequest();
730 ReadFromClient(CreateRequest("/", "1.1",
731 StringPrintf("Host: %s:999", kServerAddress)));
732 EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState());
733 }
734
TEST_F(HTTPProxyTest,ConnectAsyncConnectSuccess)735 TEST_F(HTTPProxyTest, ConnectAsyncConnectSuccess) {
736 SetupConnectComplete();
737 }
738
TEST_F(HTTPProxyTest,HTTPConnectMethod)739 TEST_F(HTTPProxyTest, HTTPConnectMethod) {
740 SetupClient();
741 ExpectAsyncConnect(kServerAddress, kConnectPort, true);
742 ExpectConnectTimeout();
743 ExpectRouteRequest();
744 ReadFromClient(kConnectQuery);
745 ExpectRepeatedInputTimeout();
746 ExpectClientData();
747 OnConnectCompletion(true, kServerFD);
748 ExpectInClientResponse("HTTP/1.1 200 OK\r\n\r\n");
749 }
750
TEST_F(HTTPProxyTest,TunnelData)751 TEST_F(HTTPProxyTest, TunnelData) {
752 SetupConnectComplete();
753
754 // The proxy is waiting for the server to be ready to accept data.
755 EXPECT_CALL(sockets(), Send(kServerFD, _, _, 0))
756 .WillOnce(Return(10));
757 ExpectServerInput();
758 WriteToServer(kServerFD);
759 EXPECT_CALL(sockets(), Send(kServerFD, _, _, 0))
760 .WillOnce(ReturnArg<2>());
761 ExpectInputTimeout();
762 WriteToServer(kServerFD);
763 EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState());
764
765 // Tunnel a reply back to the client.
766 const string server_result("200 OK ... and so on");
767 ExpectClientResult();
768 ReadFromServer(server_result);
769 EXPECT_EQ(server_result,
770 string(reinterpret_cast<const char*>(
771 GetServerData().GetConstData()),
772 GetServerData().GetLength()));
773
774 // Allow part of the result string to be sent to the client.
775 const int part = server_result.length() / 2;
776 EXPECT_CALL(sockets(), Send(kClientFD, _, server_result.length(), 0))
777 .WillOnce(Return(part));
778 ExpectInputTimeout();
779 WriteToClient(kClientFD);
780 EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState());
781
782 // The Server closes the connection while the client is still reading.
783 ExpectInputTimeout();
784 ReadFromServer("");
785 EXPECT_EQ(HTTPProxy::kStateFlushResponse, GetProxyState());
786
787 // When the last part of the response is written to the client, we close
788 // all connections.
789 EXPECT_CALL(sockets(), Send(kClientFD, _, server_result.length() - part, 0))
790 .WillOnce(ReturnArg<2>());
791 ExpectTunnelClose();
792 WriteToClient(kClientFD);
793 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
794 }
795
TEST_F(HTTPProxyTest,TunnelDataFailWriteClient)796 TEST_F(HTTPProxyTest, TunnelDataFailWriteClient) {
797 SetupConnectComplete();
798 EXPECT_CALL(sockets(), Send(kClientFD, _, _, 0))
799 .WillOnce(Return(-1));
800 ExpectTunnelClose();
801 WriteToClient(kClientFD);
802 ExpectClientReset();
803 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
804 }
805
TEST_F(HTTPProxyTest,TunnelDataFailWriteServer)806 TEST_F(HTTPProxyTest, TunnelDataFailWriteServer) {
807 SetupConnectComplete();
808 EXPECT_CALL(sockets(), Send(kServerFD, _, _, 0))
809 .WillOnce(Return(-1));
810 ExpectTunnelClose();
811 WriteToServer(kServerFD);
812 ExpectClientReset();
813 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
814 }
815
TEST_F(HTTPProxyTest,TunnelDataFailReadServer)816 TEST_F(HTTPProxyTest, TunnelDataFailReadServer) {
817 SetupConnectComplete();
818 EXPECT_CALL(sockets(), Send(kServerFD, _, _, 0))
819 .WillOnce(Return(10));
820 ExpectServerInput();
821 WriteToServer(kServerFD);
822 ExpectTunnelClose();
823 CauseReadError();
824 ExpectClientReset();
825 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
826 }
827
TEST_F(HTTPProxyTest,TunnelDataFailClientClose)828 TEST_F(HTTPProxyTest, TunnelDataFailClientClose) {
829 SetupConnectComplete();
830 ExpectTunnelClose();
831 ReadFromClient("");
832 ExpectClientReset();
833 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
834 }
835
TEST_F(HTTPProxyTest,TunnelDataFailServerClose)836 TEST_F(HTTPProxyTest, TunnelDataFailServerClose) {
837 SetupConnectComplete();
838 ExpectTunnelClose();
839 ReadFromServer("");
840 ExpectClientReset();
841 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
842 }
843
TEST_F(HTTPProxyTest,StopClient)844 TEST_F(HTTPProxyTest, StopClient) {
845 SetupConnectComplete();
846 EXPECT_CALL(sockets(), Close(kClientFD))
847 .WillOnce(Return(0));
848 EXPECT_CALL(sockets(), Close(kServerFD))
849 .WillOnce(Return(0));
850 ExpectRouteRelease();
851 StopClient();
852 ExpectClientReset();
853 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState());
854 }
855
856 } // namespace shill
857