1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stddef.h> 6 #include <string> 7 8 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/singleton.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/synchronization/waitable_event.h" 12 #include "base/threading/simple_thread.h" 13 #include "net/base/ip_endpoint.h" 14 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" 15 #include "net/quic/crypto/null_encrypter.h" 16 #include "net/quic/quic_framer.h" 17 #include "net/quic/quic_packet_creator.h" 18 #include "net/quic/quic_protocol.h" 19 #include "net/quic/test_tools/quic_connection_peer.h" 20 #include "net/quic/test_tools/quic_session_peer.h" 21 #include "net/quic/test_tools/reliable_quic_stream_peer.h" 22 #include "net/tools/quic/quic_epoll_connection_helper.h" 23 #include "net/tools/quic/quic_in_memory_cache.h" 24 #include "net/tools/quic/quic_server.h" 25 #include "net/tools/quic/quic_socket_utils.h" 26 #include "net/tools/quic/test_tools/http_message_test_utils.h" 27 #include "net/tools/quic/test_tools/quic_client_peer.h" 28 #include "net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h" 29 #include "net/tools/quic/test_tools/quic_test_client.h" 30 #include "testing/gtest/include/gtest/gtest.h" 31 32 using base::StringPiece; 33 using base::WaitableEvent; 34 using net::test::QuicConnectionPeer; 35 using net::test::QuicSessionPeer; 36 using net::test::ReliableQuicStreamPeer; 37 using std::string; 38 39 namespace net { 40 namespace tools { 41 namespace test { 42 namespace { 43 44 const char* kFooResponseBody = "Artichoke hearts make me happy."; 45 const char* kBarResponseBody = "Palm hearts are pretty delicious, also."; 46 const size_t kCongestionFeedbackFrameSize = 25; 47 // If kCongestionFeedbackFrameSize increase we need to expand this string 48 // accordingly. 49 const char* kLargeRequest = 50 "https://www.google.com/foo/test/a/request/string/longer/than/25/bytes"; 51 52 void GenerateBody(string* body, int length) { 53 body->clear(); 54 body->reserve(length); 55 for (int i = 0; i < length; ++i) { 56 body->append(1, static_cast<char>(32 + i % (126 - 32))); 57 } 58 } 59 60 61 // Simple wrapper class to run server in a thread. 62 class ServerThread : public base::SimpleThread { 63 public: 64 explicit ServerThread(IPEndPoint address, const QuicConfig& config) 65 : SimpleThread("server_thread"), 66 listening_(true, false), 67 quit_(true, false), 68 server_(config), 69 address_(address), 70 port_(0) { 71 } 72 virtual ~ServerThread() { 73 } 74 75 virtual void Run() OVERRIDE { 76 server_.Listen(address_); 77 78 port_lock_.Acquire(); 79 port_ = server_.port(); 80 port_lock_.Release(); 81 82 listening_.Signal(); 83 while (!quit_.IsSignaled()) { 84 server_.WaitForEvents(); 85 } 86 server_.Shutdown(); 87 } 88 89 int GetPort() { 90 port_lock_.Acquire(); 91 int rc = port_; 92 port_lock_.Release(); 93 return rc; 94 } 95 96 WaitableEvent* listening() { return &listening_; } 97 WaitableEvent* quit() { return &quit_; } 98 99 private: 100 WaitableEvent listening_; 101 WaitableEvent quit_; 102 base::Lock port_lock_; 103 QuicServer server_; 104 IPEndPoint address_; 105 int port_; 106 107 DISALLOW_COPY_AND_ASSIGN(ServerThread); 108 }; 109 110 class EndToEndTest : public ::testing::TestWithParam<QuicVersion> { 111 public: 112 static void SetUpTestCase() { 113 QuicInMemoryCache::GetInstance()->ResetForTests(); 114 } 115 116 protected: 117 EndToEndTest() 118 : server_hostname_("example.com"), 119 server_started_(false) { 120 net::IPAddressNumber ip; 121 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip)); 122 server_address_ = IPEndPoint(ip, 0); 123 client_config_.SetDefaults(); 124 server_config_.SetDefaults(); 125 126 AddToCache("GET", kLargeRequest, "HTTP/1.1", "200", "OK", kFooResponseBody); 127 AddToCache("GET", "https://www.google.com/foo", 128 "HTTP/1.1", "200", "OK", kFooResponseBody); 129 AddToCache("GET", "https://www.google.com/bar", 130 "HTTP/1.1", "200", "OK", kBarResponseBody); 131 version_ = GetParam(); 132 } 133 134 virtual QuicTestClient* CreateQuicClient() { 135 QuicTestClient* client = new QuicTestClient(server_address_, 136 server_hostname_, 137 false, // not secure 138 client_config_, 139 version_); 140 client->Connect(); 141 return client; 142 } 143 144 virtual bool Initialize() { 145 // Start the server first, because CreateQuicClient() attempts 146 // to connect to the server. 147 StartServer(); 148 client_.reset(CreateQuicClient()); 149 return client_->client()->connected(); 150 } 151 152 virtual void TearDown() { 153 StopServer(); 154 } 155 156 void StartServer() { 157 server_thread_.reset(new ServerThread(server_address_, server_config_)); 158 server_thread_->Start(); 159 server_thread_->listening()->Wait(); 160 server_address_ = IPEndPoint(server_address_.address(), 161 server_thread_->GetPort()); 162 server_started_ = true; 163 } 164 165 void StopServer() { 166 if (!server_started_) 167 return; 168 if (server_thread_.get()) { 169 server_thread_->quit()->Signal(); 170 server_thread_->Join(); 171 } 172 } 173 174 void AddToCache(const StringPiece& method, 175 const StringPiece& path, 176 const StringPiece& version, 177 const StringPiece& response_code, 178 const StringPiece& response_detail, 179 const StringPiece& body) { 180 BalsaHeaders request_headers, response_headers; 181 request_headers.SetRequestFirstlineFromStringPieces(method, 182 path, 183 version); 184 response_headers.SetRequestFirstlineFromStringPieces(version, 185 response_code, 186 response_detail); 187 response_headers.AppendHeader("content-length", 188 base::IntToString(body.length())); 189 190 // Check if response already exists and matches. 191 QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance(); 192 const QuicInMemoryCache::Response* cached_response = 193 cache->GetResponse(request_headers); 194 if (cached_response != NULL) { 195 string cached_response_headers_str, response_headers_str; 196 cached_response->headers().DumpToString(&cached_response_headers_str); 197 response_headers.DumpToString(&response_headers_str); 198 CHECK_EQ(cached_response_headers_str, response_headers_str); 199 CHECK_EQ(cached_response->body(), body); 200 return; 201 } 202 cache->AddResponse(request_headers, response_headers, body); 203 } 204 205 IPEndPoint server_address_; 206 string server_hostname_; 207 scoped_ptr<ServerThread> server_thread_; 208 scoped_ptr<QuicTestClient> client_; 209 bool server_started_; 210 QuicConfig client_config_; 211 QuicConfig server_config_; 212 QuicVersion version_; 213 }; 214 215 // Run all end to end tests with all supported versions. 216 INSTANTIATE_TEST_CASE_P(EndToEndTests, 217 EndToEndTest, 218 ::testing::ValuesIn(kSupportedQuicVersions)); 219 220 TEST_P(EndToEndTest, SimpleRequestResponse) { 221 // TODO(rtenneti): Delete this when NSS is supported. 222 if (!Aes128Gcm12Encrypter::IsSupported()) { 223 LOG(INFO) << "AES GCM not supported. Test skipped."; 224 return; 225 } 226 227 ASSERT_TRUE(Initialize()); 228 229 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); 230 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 231 } 232 233 // TODO(rch): figure out how to detect missing v6 supprt (like on the linux 234 // try bots) and selectively disable this test. 235 TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) { 236 // TODO(rtenneti): Delete this when NSS is supported. 237 if (!Aes128Gcm12Encrypter::IsSupported()) { 238 LOG(INFO) << "AES GCM not supported. Test skipped."; 239 return; 240 } 241 242 IPAddressNumber ip; 243 CHECK(net::ParseIPLiteralToNumber("::1", &ip)); 244 server_address_ = IPEndPoint(ip, server_address_.port()); 245 ASSERT_TRUE(Initialize()); 246 247 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); 248 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 249 } 250 251 TEST_P(EndToEndTest, SeparateFinPacket) { 252 // TODO(rtenneti): Delete this when NSS is supported. 253 if (!Aes128Gcm12Encrypter::IsSupported()) { 254 LOG(INFO) << "AES GCM not supported. Test skipped."; 255 return; 256 } 257 258 ASSERT_TRUE(Initialize()); 259 260 HTTPMessage request(HttpConstants::HTTP_1_1, 261 HttpConstants::POST, "/foo"); 262 request.set_has_complete_message(false); 263 264 client_->SendMessage(request); 265 266 client_->SendData(string(), true); 267 268 client_->WaitForResponse(); 269 EXPECT_EQ(kFooResponseBody, client_->response_body()); 270 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 271 272 request.AddBody("foo", true); 273 274 client_->SendMessage(request); 275 client_->SendData(string(), true); 276 client_->WaitForResponse(); 277 EXPECT_EQ(kFooResponseBody, client_->response_body()); 278 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 279 } 280 281 TEST_P(EndToEndTest, MultipleRequestResponse) { 282 // TODO(rtenneti): Delete this when NSS is supported. 283 if (!Aes128Gcm12Encrypter::IsSupported()) { 284 LOG(INFO) << "AES GCM not supported. Test skipped."; 285 return; 286 } 287 288 ASSERT_TRUE(Initialize()); 289 290 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); 291 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 292 EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); 293 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 294 } 295 296 TEST_P(EndToEndTest, MultipleClients) { 297 // TODO(rtenneti): Delete this when NSS is supported. 298 if (!Aes128Gcm12Encrypter::IsSupported()) { 299 LOG(INFO) << "AES GCM not supported. Test skipped."; 300 return; 301 } 302 303 ASSERT_TRUE(Initialize()); 304 scoped_ptr<QuicTestClient> client2(CreateQuicClient()); 305 306 HTTPMessage request(HttpConstants::HTTP_1_1, 307 HttpConstants::POST, "/foo"); 308 request.AddHeader("content-length", "3"); 309 request.set_has_complete_message(false); 310 311 client_->SendMessage(request); 312 client2->SendMessage(request); 313 314 client_->SendData("bar", true); 315 client_->WaitForResponse(); 316 EXPECT_EQ(kFooResponseBody, client_->response_body()); 317 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 318 319 client2->SendData("eep", true); 320 client2->WaitForResponse(); 321 EXPECT_EQ(kFooResponseBody, client2->response_body()); 322 EXPECT_EQ(200u, client2->response_headers()->parsed_response_code()); 323 } 324 325 TEST_P(EndToEndTest, RequestOverMultiplePackets) { 326 // TODO(rtenneti): Delete this when NSS is supported. 327 if (!Aes128Gcm12Encrypter::IsSupported()) { 328 LOG(INFO) << "AES GCM not supported. Test skipped."; 329 return; 330 } 331 332 ASSERT_TRUE(Initialize()); 333 // Set things up so we have a small payload, to guarantee fragmentation. 334 // A congestion feedback frame can't be split into multiple packets, make sure 335 // that our packet have room for at least this amount after the normal headers 336 // are added. 337 338 // TODO(rch) handle this better when we have different encryption options. 339 const size_t kStreamDataLength = 3; 340 const QuicStreamId kStreamId = 1u; 341 const QuicStreamOffset kStreamOffset = 0u; 342 size_t stream_payload_size = 343 QuicFramer::GetMinStreamFrameSize( 344 GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength; 345 size_t min_payload_size = 346 std::max(kCongestionFeedbackFrameSize, stream_payload_size); 347 size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size); 348 // TODO(satyashekhar): Fix this when versioning is implemented. 349 client_->options()->max_packet_length = 350 GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, 351 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) + 352 ciphertext_size; 353 354 // Make sure our request is too large to fit in one packet. 355 EXPECT_GT(strlen(kLargeRequest), min_payload_size); 356 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest)); 357 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 358 } 359 360 TEST_P(EndToEndTest, MultipleFramesRandomOrder) { 361 // TODO(rtenneti): Delete this when NSS is supported. 362 if (!Aes128Gcm12Encrypter::IsSupported()) { 363 LOG(INFO) << "AES GCM not supported. Test skipped."; 364 return; 365 } 366 367 ASSERT_TRUE(Initialize()); 368 // Set things up so we have a small payload, to guarantee fragmentation. 369 // A congestion feedback frame can't be split into multiple packets, make sure 370 // that our packet have room for at least this amount after the normal headers 371 // are added. 372 373 // TODO(rch) handle this better when we have different encryption options. 374 const size_t kStreamDataLength = 3; 375 const QuicStreamId kStreamId = 1u; 376 const QuicStreamOffset kStreamOffset = 0u; 377 size_t stream_payload_size = 378 QuicFramer::GetMinStreamFrameSize( 379 GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength; 380 size_t min_payload_size = 381 std::max(kCongestionFeedbackFrameSize, stream_payload_size); 382 size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size); 383 // TODO(satyashekhar): Fix this when versioning is implemented. 384 client_->options()->max_packet_length = 385 GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion, 386 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) + 387 ciphertext_size; 388 client_->options()->random_reorder = true; 389 390 // Make sure our request is too large to fit in one packet. 391 EXPECT_GT(strlen(kLargeRequest), min_payload_size); 392 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest)); 393 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 394 } 395 396 TEST_P(EndToEndTest, PostMissingBytes) { 397 // TODO(rtenneti): Delete this when NSS is supported. 398 if (!Aes128Gcm12Encrypter::IsSupported()) { 399 LOG(INFO) << "AES GCM not supported. Test skipped."; 400 return; 401 } 402 403 ASSERT_TRUE(Initialize()); 404 405 // Add a content length header with no body. 406 HTTPMessage request(HttpConstants::HTTP_1_1, 407 HttpConstants::POST, "/foo"); 408 request.AddHeader("content-length", "3"); 409 request.set_skip_message_validation(true); 410 411 // This should be detected as stream fin without complete request, 412 // triggering an error response. 413 client_->SendCustomSynchronousRequest(request); 414 EXPECT_EQ("bad", client_->response_body()); 415 EXPECT_EQ(500u, client_->response_headers()->parsed_response_code()); 416 } 417 418 TEST_P(EndToEndTest, LargePost) { 419 // TODO(rtenneti): Delete this when NSS is supported. 420 if (!Aes128Gcm12Encrypter::IsSupported()) { 421 LOG(INFO) << "AES GCM not supported. Test skipped."; 422 return; 423 } 424 425 // Connect with lower fake packet loss than we'd like to test. Until 426 // b/10126687 is fixed, losing handshake packets is pretty brutal. 427 // FLAGS_fake_packet_loss_percentage = 5; 428 ASSERT_TRUE(Initialize()); 429 430 // Wait for the server SHLO before upping the packet loss. 431 client_->client()->WaitForCryptoHandshakeConfirmed(); 432 // FLAGS_fake_packet_loss_percentage = 30; 433 434 string body; 435 GenerateBody(&body, 10240); 436 437 HTTPMessage request(HttpConstants::HTTP_1_1, 438 HttpConstants::POST, "/foo"); 439 request.AddBody(body, true); 440 441 EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request)); 442 } 443 444 // TODO(ianswett): Enable once b/9295090 is fixed. 445 TEST_P(EndToEndTest, DISABLED_LargePostFEC) { 446 // FLAGS_fake_packet_loss_percentage = 30; 447 ASSERT_TRUE(Initialize()); 448 client_->options()->max_packets_per_fec_group = 6; 449 450 // TODO(rtenneti): Delete this when NSS is supported. 451 if (!Aes128Gcm12Encrypter::IsSupported()) { 452 LOG(INFO) << "AES GCM not supported. Test skipped."; 453 return; 454 } 455 456 // FLAGS_fake_packet_loss_percentage = 30; 457 ASSERT_TRUE(Initialize()); 458 client_->options()->max_packets_per_fec_group = 6; 459 460 string body; 461 GenerateBody(&body, 10240); 462 463 HTTPMessage request(HttpConstants::HTTP_1_1, 464 HttpConstants::POST, "/foo"); 465 request.AddBody(body, true); 466 467 EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request)); 468 } 469 470 /*TEST_P(EndToEndTest, PacketTooLarge) { 471 FLAGS_quic_allow_oversized_packets_for_test = true; 472 ASSERT_TRUE(Initialize()); 473 474 string body; 475 GenerateBody(&body, kMaxPacketSize); 476 477 HTTPMessage request(HttpConstants::HTTP_1_1, 478 HttpConstants::POST, "/foo"); 479 request.AddBody(body, true); 480 client_->options()->max_packet_length = 20480; 481 482 EXPECT_EQ("", client_->SendCustomSynchronousRequest(request)); 483 EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); 484 EXPECT_EQ(QUIC_PACKET_TOO_LARGE, client_->connection_error()); 485 }*/ 486 487 TEST_P(EndToEndTest, InvalidStream) { 488 // TODO(rtenneti): Delete this when NSS is supported. 489 if (!Aes128Gcm12Encrypter::IsSupported()) { 490 LOG(INFO) << "AES GCM not supported. Test skipped."; 491 return; 492 } 493 494 ASSERT_TRUE(Initialize()); 495 496 string body; 497 GenerateBody(&body, kMaxPacketSize); 498 499 HTTPMessage request(HttpConstants::HTTP_1_1, 500 HttpConstants::POST, "/foo"); 501 request.AddBody(body, true); 502 // Force the client to write with a stream ID belonging to a nonexistent 503 // server-side stream. 504 QuicSessionPeer::SetNextStreamId(client_->client()->session(), 2); 505 506 client_->SendCustomSynchronousRequest(request); 507 // EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); 508 EXPECT_EQ(QUIC_PACKET_FOR_NONEXISTENT_STREAM, client_->connection_error()); 509 } 510 511 // TODO(rch): this test seems to cause net_unittests timeouts :| 512 TEST_P(EndToEndTest, DISABLED_MultipleTermination) { 513 // TODO(rtenneti): Delete this when NSS is supported. 514 if (!Aes128Gcm12Encrypter::IsSupported()) { 515 LOG(INFO) << "AES GCM not supported. Test skipped."; 516 return; 517 } 518 519 ASSERT_TRUE(Initialize()); 520 scoped_ptr<QuicTestClient> client2(CreateQuicClient()); 521 522 HTTPMessage request(HttpConstants::HTTP_1_1, 523 HttpConstants::POST, "/foo"); 524 request.AddHeader("content-length", "3"); 525 request.set_has_complete_message(false); 526 527 // Set the offset so we won't frame. Otherwise when we pick up termination 528 // before HTTP framing is complete, we send an error and close the stream, 529 // and the second write is picked up as writing on a closed stream. 530 QuicReliableClientStream* stream = client_->GetOrCreateStream(); 531 ASSERT_TRUE(stream != NULL); 532 ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream); 533 534 client_->SendData("bar", true); 535 536 // By default the stream protects itself from writes after terminte is set. 537 // Override this to test the server handling buggy clients. 538 ReliableQuicStreamPeer::SetWriteSideClosed( 539 false, client_->GetOrCreateStream()); 540 541 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST) 542 #if !defined(DCHECK_ALWAYS_ON) 543 EXPECT_DEBUG_DEATH({ 544 client_->SendData("eep", true); 545 client_->WaitForResponse(); 546 EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error()); 547 }, 548 "Check failed: !fin_buffered_"); 549 #else 550 EXPECT_DEATH({ 551 client_->SendData("eep", true); 552 client_->WaitForResponse(); 553 EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error()); 554 }, 555 "Check failed: !fin_buffered_"); 556 #endif 557 #endif 558 } 559 560 TEST_P(EndToEndTest, Timeout) { 561 client_config_.set_idle_connection_state_lifetime( 562 QuicTime::Delta::FromMicroseconds(500), 563 QuicTime::Delta::FromMicroseconds(500)); 564 // Note: we do NOT ASSERT_TRUE: we may time out during initial handshake: 565 // that's enough to validate timeout in this case. 566 Initialize(); 567 while (client_->client()->connected()) { 568 client_->client()->WaitForEvents(); 569 } 570 } 571 572 TEST_P(EndToEndTest, LimitMaxOpenStreams) { 573 // Server limits the number of max streams to 2. 574 server_config_.set_max_streams_per_connection(2, 2); 575 // Client tries to negotiate for 10. 576 client_config_.set_max_streams_per_connection(10, 5); 577 578 ASSERT_TRUE(Initialize()); 579 client_->client()->WaitForCryptoHandshakeConfirmed(); 580 QuicConfig* client_negotiated_config = client_->client()->session()->config(); 581 EXPECT_EQ(2u, client_negotiated_config->max_streams_per_connection()); 582 } 583 584 TEST_P(EndToEndTest, ResetConnection) { 585 // TODO(rtenneti): Delete this when NSS is supported. 586 if (!Aes128Gcm12Encrypter::IsSupported()) { 587 LOG(INFO) << "AES GCM not supported. Test skipped."; 588 return; 589 } 590 591 ASSERT_TRUE(Initialize()); 592 593 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); 594 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 595 client_->ResetConnection(); 596 EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); 597 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 598 } 599 600 class WrongAddressWriter : public QuicPacketWriter { 601 public: 602 explicit WrongAddressWriter(int fd) : fd_(fd) { 603 IPAddressNumber ip; 604 CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip)); 605 self_address_ = IPEndPoint(ip, 0); 606 } 607 608 virtual int WritePacket(const char* buffer, size_t buf_len, 609 const IPAddressNumber& real_self_address, 610 const IPEndPoint& peer_address, 611 QuicBlockedWriterInterface* blocked_writer, 612 int* error) OVERRIDE { 613 return QuicSocketUtils::WritePacket(fd_, buffer, buf_len, 614 self_address_.address(), peer_address, 615 error); 616 } 617 618 IPEndPoint self_address_; 619 int fd_; 620 }; 621 622 TEST_P(EndToEndTest, ConnectionMigration) { 623 // TODO(rtenneti): Delete this when NSS is supported. 624 if (!Aes128Gcm12Encrypter::IsSupported()) { 625 LOG(INFO) << "AES GCM not supported. Test skipped."; 626 return; 627 } 628 629 ASSERT_TRUE(Initialize()); 630 631 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); 632 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); 633 634 WrongAddressWriter writer(QuicClientPeer::GetFd(client_->client())); 635 QuicEpollConnectionHelper* helper = 636 reinterpret_cast<QuicEpollConnectionHelper*>( 637 QuicConnectionPeer::GetHelper( 638 client_->client()->session()->connection())); 639 QuicEpollConnectionHelperPeer::SetWriter(helper, &writer); 640 641 client_->SendSynchronousRequest("/bar"); 642 QuicEpollConnectionHelperPeer::SetWriter(helper, NULL); 643 644 EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error()); 645 EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS, client_->connection_error()); 646 } 647 648 } // namespace 649 } // namespace test 650 } // namespace tools 651 } // namespace net 652