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: 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: 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 } 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 } 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 } 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 } 163 void InvokeSyncConnect(const IPAddress& /*address*/, int /*port*/) { 164 proxy_.OnConnectCompletion(true, kServerFD); 165 } 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 174 const ByteString& GetClientData() { 175 return proxy_.client_data_; 176 } 177 HTTPProxy* proxy() { return &proxy_; } 178 HTTPProxy::State GetProxyState() { 179 return proxy_.state_; 180 } 181 const ByteString& GetServerData() { 182 return proxy_.server_data_; 183 } 184 MockSockets& sockets() { return sockets_; } 185 MockEventDispatcher& dispatcher() { return dispatcher_; } 186 187 188 // Expectations 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 } 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 } 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 } 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 } 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 } 259 void ExpectTimeout(int timeout) { 260 EXPECT_CALL(dispatcher_, PostDelayedTask(_, timeout * 1000)); 261 } 262 void ExpectClientHeaderTimeout() { 263 ExpectTimeout(HTTPProxy::kClientHeaderTimeoutSeconds); 264 } 265 void ExpectConnectTimeout() { 266 ExpectTimeout(HTTPProxy::kConnectTimeoutSeconds); 267 } 268 void ExpectInputTimeout() { 269 ExpectTimeout(HTTPProxy::kInputTimeoutSeconds); 270 } 271 void ExpectRepeatedInputTimeout() { 272 EXPECT_CALL(dispatcher_, 273 PostDelayedTask(_, HTTPProxy::kInputTimeoutSeconds * 1000)) 274 .Times(AnyNumber()); 275 } 276 void ExpectTransactionTimeout() { 277 ExpectTimeout(HTTPProxy::kTransactionTimeoutSeconds); 278 } 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 } 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 } 290 void ExpectClientInternalError() { 291 ExpectClientError(500, HTTPProxy::kInternalErrorMsg); 292 } 293 void ExpectClientVersion(const string& version) { 294 EXPECT_EQ(version, proxy_.client_version_); 295 } 296 void ExpectServerHostname(const string& hostname) { 297 EXPECT_EQ(hostname, proxy_.server_hostname_); 298 } 299 void ExpectFirstLine(const string& line) { 300 EXPECT_EQ(line, proxy_.client_headers_[0] + "\r\n"); 301 } 302 void ExpectDNSRequest(const string& host, bool return_value) { 303 EXPECT_CALL(*dns_client_, Start(StrEq(host), _)) 304 .WillOnce(Return(return_value)); 305 } 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 } 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 } 316 void ExpectClientData() { 317 EXPECT_CALL(dispatcher(), 318 CreateReadyHandler(kClientFD, 319 IOHandler::kModeOutput, 320 CallbackEq(proxy_.write_client_callback_))) 321 .WillOnce(ReturnNew<IOHandler>()); 322 } 323 void ExpectClientResult() { 324 ExpectClientData(); 325 ExpectInputTimeout(); 326 } 327 void ExpectServerInput() { 328 EXPECT_CALL(dispatcher(), 329 CreateInputHandler(kServerFD, 330 CallbackEq(proxy_.read_server_callback_), _)) 331 .WillOnce(ReturnNew<IOHandler>()); 332 ExpectInputTimeout(); 333 } 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 } 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 } 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 } 356 void ExpectRouteRequest() { 357 EXPECT_CALL(*connection_.get(), RequestRouting()); 358 } 359 void ExpectRouteRelease() { 360 EXPECT_CALL(*connection_.get(), ReleaseRouting()); 361 } 362 363 // Callers for various private routines in the proxy 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 } 376 void AcceptClient(int fd) { 377 proxy_.AcceptClient(fd); 378 } 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 } 384 void GetDNSResultSuccess(const IPAddress& address) { 385 Error error; 386 proxy_.GetDNSResult(error, address); 387 } 388 void OnConnectCompletion(bool result, int sockfd) { 389 proxy_.OnConnectCompletion(result, sockfd); 390 } 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 } 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 } 405 void SendClientError(int code, const string& error) { 406 proxy_.SendClientError(code, error); 407 EXPECT_FALSE(proxy_.server_data_.IsEmpty()); 408 } 409 void StopClient() { 410 EXPECT_CALL(*dns_client_, Stop()); 411 EXPECT_CALL(*server_async_connection_, Stop()); 412 proxy_.StopClient(); 413 } 414 void StopProxy() { 415 ExpectStop(); 416 proxy_.Stop(); 417 server_async_connection_ = nullptr; 418 dns_client_ = nullptr; 419 ExpectReset(); 420 } 421 void WriteToClient(int fd) { 422 proxy_.WriteToClient(fd); 423 } 424 void WriteToServer(int fd) { 425 proxy_.WriteToServer(fd); 426 } 427 428 void SetupClient() { 429 ExpectStart(); 430 ASSERT_TRUE(StartProxy()); 431 ExpectClientInput(kClientFD); 432 AcceptClient(kProxyFD); 433 EXPECT_EQ(HTTPProxy::kStateReadClientHeader, GetProxyState()); 434 } 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 } 444 void SetupConnect() { 445 SetupConnectWithRequest("/", "1.1", "Host: www.chromium.org:40506"); 446 } 447 void SetupConnectAsync() { 448 SetupClient(); 449 ExpectAsyncConnect(kServerAddress, kServerPort, true); 450 ExpectConnectTimeout(); 451 SetupConnect(); 452 } 453 void SetupConnectComplete() { 454 SetupConnectAsync(); 455 ExpectServerOutput(); 456 OnConnectCompletion(true, kServerFD); 457 EXPECT_EQ(HTTPProxy::kStateTunnelData, GetProxyState()); 458 } 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 478 TEST_F(HTTPProxyTest, StartFailSocket) { 479 EXPECT_CALL(sockets(), Socket(_, _, _)) 480 .WillOnce(Return(-1)); 481 EXPECT_FALSE(StartProxy()); 482 ExpectReset(); 483 } 484 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 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 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 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 541 TEST_F(HTTPProxyTest, StartSuccess) { 542 ExpectStart(); 543 EXPECT_TRUE(StartProxy()); 544 } 545 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 571 TEST_F(HTTPProxyTest, ReadMissingURL) { 572 SetupClient(); 573 ExpectClientResult(); 574 ReadFromClient(kBadHeaderMissingURL); 575 ExpectClientError(501, "Server could not parse HTTP method"); 576 } 577 578 TEST_F(HTTPProxyTest, ReadMissingVersion) { 579 SetupClient(); 580 ExpectClientResult(); 581 ReadFromClient(kBadHeaderMissingVersion); 582 ExpectClientError(501, "Server only accepts HTTP/1.x requests"); 583 } 584 585 TEST_F(HTTPProxyTest, ReadBadHostname) { 586 SetupClient(); 587 ExpectClientResult(); 588 ReadFromClient(kBadHostnameLine); 589 ExpectClientInternalError(); 590 } 591 592 TEST_F(HTTPProxyTest, GoodFirstLineWithoutURL) { 593 SetupClient(); 594 ExpectClientHeaderTimeout(); 595 ReadFromClient(kBasicGetHeader); 596 ExpectClientVersion("1.1"); 597 ExpectServerHostname(""); 598 ExpectFirstLine(kBasicGetHeader); 599 } 600 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 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 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 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 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 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 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 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 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. 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 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 710 TEST_F(HTTPProxyTest, ConnectAsyncConnectFailure) { 711 SetupConnectAsync(); 712 ExpectClientResult(); 713 OnConnectCompletion(false, -1); 714 ExpectClientError(500, "Socket connection delayed failure"); 715 } 716 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 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 735 TEST_F(HTTPProxyTest, ConnectAsyncConnectSuccess) { 736 SetupConnectComplete(); 737 } 738 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 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 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 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 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 828 TEST_F(HTTPProxyTest, TunnelDataFailClientClose) { 829 SetupConnectComplete(); 830 ExpectTunnelClose(); 831 ReadFromClient(""); 832 ExpectClientReset(); 833 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState()); 834 } 835 836 TEST_F(HTTPProxyTest, TunnelDataFailServerClose) { 837 SetupConnectComplete(); 838 ExpectTunnelClose(); 839 ReadFromServer(""); 840 ExpectClientReset(); 841 EXPECT_EQ(HTTPProxy::kStateWaitConnection, GetProxyState()); 842 } 843 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