Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/server/http_server.h" | 5 #include "net/server/http_server.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 125 return false; | 125 return false; |
| 126 while (!IsCompleteResponse(*message)) { | 126 while (!IsCompleteResponse(*message)) { |
| 127 std::string chunk; | 127 std::string chunk; |
| 128 if (!Read(&chunk, 1)) | 128 if (!Read(&chunk, 1)) |
| 129 return false; | 129 return false; |
| 130 message->append(chunk); | 130 message->append(chunk); |
| 131 } | 131 } |
| 132 return true; | 132 return true; |
| 133 } | 133 } |
| 134 | 134 |
| 135 TCPClientSocket& socket() { return *socket_; } | |
| 136 | |
| 135 private: | 137 private: |
| 136 void OnConnect(const base::Closure& quit_loop, int result) { | 138 void OnConnect(const base::Closure& quit_loop, int result) { |
| 137 connect_result_ = result; | 139 connect_result_ = result; |
| 138 quit_loop.Run(); | 140 quit_loop.Run(); |
| 139 } | 141 } |
| 140 | 142 |
| 141 void Write() { | 143 void Write() { |
| 142 int result = socket_->Write( | 144 int result = socket_->Write( |
| 143 write_buffer_.get(), | 145 write_buffer_.get(), |
| 144 write_buffer_->BytesRemaining(), | 146 write_buffer_->BytesRemaining(), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 HttpServerTest() : quit_after_request_count_(0) {} | 193 HttpServerTest() : quit_after_request_count_(0) {} |
| 192 | 194 |
| 193 void SetUp() override { | 195 void SetUp() override { |
| 194 std::unique_ptr<ServerSocket> server_socket( | 196 std::unique_ptr<ServerSocket> server_socket( |
| 195 new TCPServerSocket(NULL, NetLog::Source())); | 197 new TCPServerSocket(NULL, NetLog::Source())); |
| 196 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); | 198 server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); |
| 197 server_.reset(new HttpServer(std::move(server_socket), this)); | 199 server_.reset(new HttpServer(std::move(server_socket), this)); |
| 198 ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk()); | 200 ASSERT_THAT(server_->GetLocalAddress(&server_address_), IsOk()); |
| 199 } | 201 } |
| 200 | 202 |
| 201 void OnConnect(int connection_id) override {} | 203 void OnConnect(int connection_id) override { |
| 204 DCHECK(connection_map_.find(connection_id) == connection_map_.end()); | |
| 205 connection_map_[connection_id] = true; | |
| 206 } | |
| 202 | 207 |
| 203 void OnHttpRequest(int connection_id, | 208 void OnHttpRequest(int connection_id, |
| 204 const HttpServerRequestInfo& info) override { | 209 const HttpServerRequestInfo& info) override { |
| 205 requests_.push_back(std::make_pair(info, connection_id)); | 210 requests_.push_back(std::make_pair(info, connection_id)); |
| 206 if (requests_.size() == quit_after_request_count_) | 211 if (requests_.size() == quit_after_request_count_) |
| 207 run_loop_quit_func_.Run(); | 212 run_loop_quit_func_.Run(); |
| 208 } | 213 } |
| 209 | 214 |
| 210 void OnWebSocketRequest(int connection_id, | 215 void OnWebSocketRequest(int connection_id, |
| 211 const HttpServerRequestInfo& info) override { | 216 const HttpServerRequestInfo& info) override { |
| 212 NOTREACHED(); | 217 NOTREACHED(); |
| 213 } | 218 } |
| 214 | 219 |
| 215 void OnWebSocketMessage(int connection_id, const std::string& data) override { | 220 void OnWebSocketMessage(int connection_id, const std::string& data) override { |
| 216 NOTREACHED(); | 221 NOTREACHED(); |
| 217 } | 222 } |
| 218 | 223 |
| 219 void OnClose(int connection_id) override {} | 224 void OnClose(int connection_id) override { |
| 225 DCHECK(connection_map_.find(connection_id) != connection_map_.end()); | |
| 226 connection_map_[connection_id] = false; | |
| 227 } | |
| 220 | 228 |
| 221 bool RunUntilRequestsReceived(size_t count) { | 229 bool RunUntilRequestsReceived(size_t count) { |
| 222 quit_after_request_count_ = count; | 230 quit_after_request_count_ = count; |
| 223 if (requests_.size() == count) | 231 if (requests_.size() == count) |
| 224 return true; | 232 return true; |
| 225 | 233 |
| 226 base::RunLoop run_loop; | 234 base::RunLoop run_loop; |
| 227 run_loop_quit_func_ = run_loop.QuitClosure(); | 235 run_loop_quit_func_ = run_loop.QuitClosure(); |
| 228 bool success = RunLoopWithTimeout(&run_loop); | 236 bool success = RunLoopWithTimeout(&run_loop); |
| 229 run_loop_quit_func_.Reset(); | 237 run_loop_quit_func_.Reset(); |
| 230 return success; | 238 return success; |
| 231 } | 239 } |
| 232 | 240 |
| 233 HttpServerRequestInfo GetRequest(size_t request_index) { | 241 HttpServerRequestInfo GetRequest(size_t request_index) { |
| 234 return requests_[request_index].first; | 242 return requests_[request_index].first; |
| 235 } | 243 } |
| 236 | 244 |
| 237 int GetConnectionId(size_t request_index) { | 245 int GetConnectionId(size_t request_index) { |
| 238 return requests_[request_index].second; | 246 return requests_[request_index].second; |
| 239 } | 247 } |
| 240 | 248 |
| 241 void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) { | 249 void HandleAcceptResult(std::unique_ptr<StreamSocket> socket) { |
| 242 server_->accepted_socket_.reset(socket.release()); | 250 server_->accepted_socket_.reset(socket.release()); |
| 243 server_->HandleAcceptResult(OK); | 251 server_->HandleAcceptResult(OK); |
| 244 } | 252 } |
| 245 | 253 |
| 254 std::unordered_map<int, bool>& connection_map() { return connection_map_; } | |
| 255 | |
| 246 protected: | 256 protected: |
| 247 std::unique_ptr<HttpServer> server_; | 257 std::unique_ptr<HttpServer> server_; |
| 248 IPEndPoint server_address_; | 258 IPEndPoint server_address_; |
| 249 base::Closure run_loop_quit_func_; | 259 base::Closure run_loop_quit_func_; |
| 250 std::vector<std::pair<HttpServerRequestInfo, int> > requests_; | 260 std::vector<std::pair<HttpServerRequestInfo, int> > requests_; |
| 261 std::unordered_map<int /* connection_id */, bool /* connected */> | |
| 262 connection_map_; | |
| 251 | 263 |
| 252 private: | 264 private: |
| 253 size_t quit_after_request_count_; | 265 size_t quit_after_request_count_; |
| 254 }; | 266 }; |
| 255 | 267 |
| 256 namespace { | 268 namespace { |
| 257 | 269 |
| 258 class WebSocketTest : public HttpServerTest { | 270 class WebSocketTest : public HttpServerTest { |
| 259 void OnHttpRequest(int connection_id, | 271 void OnHttpRequest(int connection_id, |
| 260 const HttpServerRequestInfo& info) override { | 272 const HttpServerRequestInfo& info) override { |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 server_->SendRaw(GetConnectionId(0), "Raw Data "); | 477 server_->SendRaw(GetConnectionId(0), "Raw Data "); |
| 466 server_->SendRaw(GetConnectionId(0), "More Data"); | 478 server_->SendRaw(GetConnectionId(0), "More Data"); |
| 467 server_->SendRaw(GetConnectionId(0), "Third Piece of Data"); | 479 server_->SendRaw(GetConnectionId(0), "Third Piece of Data"); |
| 468 | 480 |
| 469 const std::string expected_response("Raw Data More DataThird Piece of Data"); | 481 const std::string expected_response("Raw Data More DataThird Piece of Data"); |
| 470 std::string response; | 482 std::string response; |
| 471 ASSERT_TRUE(client.Read(&response, expected_response.length())); | 483 ASSERT_TRUE(client.Read(&response, expected_response.length())); |
| 472 ASSERT_EQ(expected_response, response); | 484 ASSERT_EQ(expected_response, response); |
| 473 } | 485 } |
| 474 | 486 |
| 487 TEST_F(HttpServerTest, WrongProtocolRequest) { | |
| 488 const char* const kBadProtocolRequests[] = { | |
| 489 "GET /test HTTP/1.0\r\n\r\n", | |
| 490 "GET /test foo\r\n\r\n", | |
| 491 "GET /test \r\n\r\n", | |
| 492 }; | |
| 493 | |
| 494 for (size_t i = 0; i < arraysize(kBadProtocolRequests); ++i) { | |
| 495 TestHttpClient client; | |
| 496 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); | |
| 497 | |
| 498 client.Send(kBadProtocolRequests[i]); | |
| 499 ASSERT_FALSE(RunUntilRequestsReceived(1)); | |
| 500 | |
| 501 // Assert that the delegate was updated properly. | |
| 502 ASSERT_EQ(1u, connection_map().size()); | |
| 503 ASSERT_FALSE(connection_map().begin()->second); | |
| 504 | |
| 505 // Assert that the socket was opened then closed. | |
| 506 ASSERT_TRUE(client.socket().WasEverUsed()); | |
| 507 ASSERT_FALSE(client.socket().IsConnected()); | |
|
mmenke
2016/09/15 17:40:12
This is potentially racy - the server could exit t
slan
2016/09/16 22:35:30
Done.
| |
| 508 | |
| 509 // Reset the state of the connection map. | |
| 510 connection_map().clear(); | |
| 511 } | |
| 512 } | |
| 513 | |
| 475 class MockStreamSocket : public StreamSocket { | 514 class MockStreamSocket : public StreamSocket { |
| 476 public: | 515 public: |
| 477 MockStreamSocket() | 516 MockStreamSocket() |
| 478 : connected_(true), | 517 : connected_(true), |
| 479 read_buf_(NULL), | 518 read_buf_(NULL), |
| 480 read_buf_len_(0) {} | 519 read_buf_len_(0) {} |
| 481 | 520 |
| 482 // StreamSocket | 521 // StreamSocket |
| 483 int Connect(const CompletionCallback& callback) override { | 522 int Connect(const CompletionCallback& callback) override { |
| 484 return ERR_NOT_IMPLEMENTED; | 523 return ERR_NOT_IMPLEMENTED; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 633 ASSERT_TRUE(client.ReadResponse(&response3)); | 672 ASSERT_TRUE(client.ReadResponse(&response3)); |
| 634 ASSERT_TRUE(base::StartsWith(response3, "HTTP/1.1 200 OK", | 673 ASSERT_TRUE(base::StartsWith(response3, "HTTP/1.1 200 OK", |
| 635 base::CompareCase::SENSITIVE)); | 674 base::CompareCase::SENSITIVE)); |
| 636 ASSERT_TRUE(base::EndsWith(response3, "Content for /test3", | 675 ASSERT_TRUE(base::EndsWith(response3, "Content for /test3", |
| 637 base::CompareCase::SENSITIVE)); | 676 base::CompareCase::SENSITIVE)); |
| 638 } | 677 } |
| 639 | 678 |
| 640 class CloseOnConnectHttpServerTest : public HttpServerTest { | 679 class CloseOnConnectHttpServerTest : public HttpServerTest { |
| 641 public: | 680 public: |
| 642 void OnConnect(int connection_id) override { | 681 void OnConnect(int connection_id) override { |
| 682 HttpServerTest::OnConnect(connection_id); | |
| 643 connection_ids_.push_back(connection_id); | 683 connection_ids_.push_back(connection_id); |
| 644 server_->Close(connection_id); | 684 server_->Close(connection_id); |
| 645 } | 685 } |
| 646 | 686 |
| 647 protected: | 687 protected: |
| 648 std::vector<int> connection_ids_; | 688 std::vector<int> connection_ids_; |
| 649 }; | 689 }; |
| 650 | 690 |
| 651 TEST_F(CloseOnConnectHttpServerTest, ServerImmediatelyClosesConnection) { | 691 TEST_F(CloseOnConnectHttpServerTest, ServerImmediatelyClosesConnection) { |
| 652 TestHttpClient client; | 692 TestHttpClient client; |
| 653 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); | 693 ASSERT_THAT(client.ConnectAndWait(server_address_), IsOk()); |
| 654 client.Send("GET / HTTP/1.1\r\n\r\n"); | 694 client.Send("GET / HTTP/1.1\r\n\r\n"); |
| 655 ASSERT_FALSE(RunUntilRequestsReceived(1)); | 695 ASSERT_FALSE(RunUntilRequestsReceived(1)); |
| 656 ASSERT_EQ(1ul, connection_ids_.size()); | 696 ASSERT_EQ(1ul, connection_ids_.size()); |
| 657 ASSERT_EQ(0ul, requests_.size()); | 697 ASSERT_EQ(0ul, requests_.size()); |
| 658 } | 698 } |
| 659 | 699 |
| 660 } // namespace | 700 } // namespace |
| 661 | 701 |
| 662 } // namespace net | 702 } // namespace net |
| OLD | NEW |