Index: net/tools/quic/end_to_end_test.cc |
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc |
index ef394b95f2453d21588a6cd1b170418d42ce7697..e06a9eda36db9f2d4eb9c59887a1967a13602c14 100644 |
--- a/net/tools/quic/end_to_end_test.cc |
+++ b/net/tools/quic/end_to_end_test.cc |
@@ -28,6 +28,7 @@ |
#include "net/quic/test_tools/quic_test_utils.h" |
#include "net/quic/test_tools/reliable_quic_stream_peer.h" |
#include "net/test/gtest_util.h" |
+#include "net/tools/epoll_server/epoll_server.h" |
#include "net/tools/quic/quic_epoll_connection_helper.h" |
#include "net/tools/quic/quic_in_memory_cache.h" |
#include "net/tools/quic/quic_packet_writer_wrapper.h" |
@@ -46,6 +47,7 @@ |
using base::StringPiece; |
using base::WaitableEvent; |
+using net::EpollServer; |
using net::test::GenerateBody; |
using net::test::QuicConnectionPeer; |
using net::test::QuicSessionPeer; |
@@ -953,7 +955,10 @@ class WrongAddressWriter : public QuicPacketWriterWrapper { |
IPEndPoint self_address_; |
}; |
-TEST_P(EndToEndTest, ConnectionMigration) { |
+TEST_P(EndToEndTest, ConnectionMigrationClientIPChanged) { |
+ // Tests that the client's IP can not change during an established QUIC |
+ // connection. If it changes, the connection is closed by the server as we do |
+ // not yet support IP migration. |
ASSERT_TRUE(Initialize()); |
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); |
@@ -971,6 +976,59 @@ TEST_P(EndToEndTest, ConnectionMigration) { |
EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS, client_->connection_error()); |
} |
+TEST_P(EndToEndTest, ConnectionMigrationClientPortChanged) { |
+ // Tests that the client's port can change during an established QUIC |
+ // connection, and that doing so does not result in the connection being |
+ // closed by the server. |
+ FLAGS_quic_allow_port_migration = true; |
+ |
+ ASSERT_TRUE(Initialize()); |
+ |
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo")); |
+ EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); |
+ |
+ // Store the client address which was used to send the first request. |
+ IPEndPoint old_address = client_->client()->client_address(); |
+ |
+ // Stop listening on the old FD. |
+ EpollServer* eps = client_->client()->epoll_server(); |
+ int old_fd = client_->client()->fd(); |
+ eps->UnregisterFD(old_fd); |
+ close(old_fd); |
+ |
+ // Create a new socket, which will result in a new ephemeral port. |
+ QuicClientPeer::CreateUDPSocket(client_->client()); |
+ |
+ // The packet writer needs to be updated to use the new FD. |
+ client_->client()->CreateQuicPacketWriter(); |
+ |
+ // Change the internal state of the client and connection to use the new port, |
+ // this is done because in a real NAT rebinding the client wouldn't see any |
+ // port change, and so expects no change to incoming port. |
+ // This is kind of ugly, but needed as we are simply swapping out the client |
+ // FD rather than any more complex NAT rebinding simulation. |
+ int new_port = client_->client()->client_address().port(); |
+ QuicClientPeer::SetClientPort(client_->client(), new_port); |
+ QuicConnectionPeer::SetSelfAddress( |
+ client_->client()->session()->connection(), |
+ IPEndPoint( |
+ client_->client()->session()->connection()->self_address().address(), |
+ new_port)); |
+ |
+ // Register the new FD for epoll events. |
+ int new_fd = client_->client()->fd(); |
+ eps->RegisterFD(new_fd, client_->client(), EPOLLIN | EPOLLOUT | EPOLLET); |
+ |
+ // Send a second request, using the new FD. |
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar")); |
+ EXPECT_EQ(200u, client_->response_headers()->parsed_response_code()); |
+ |
+ // Verify that the client's ephemeral port is different. |
+ IPEndPoint new_address = client_->client()->client_address(); |
+ EXPECT_EQ(old_address.address(), new_address.address()); |
+ EXPECT_NE(old_address.port(), new_address.port()); |
+} |
+ |
TEST_P(EndToEndTest, DifferentFlowControlWindows) { |
// Client and server can set different initial flow control receive windows. |
// These are sent in CHLO/SHLO. Tests that these values are exchanged properly |