• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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