Commit 217455a1 authored by jri's avatar jri Committed by Commit bot

Implements migration of a QUIC connection to a different destination address...

Implements migration of a QUIC connection to a different destination address if specified by the server in an ASAD tag in the Server Hello. Quietly falls back to original socket if creation and connecting a new socket fails.

R=rch@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2124753005
Cr-Commit-Position: refs/heads/master@{#405262}
parent d0318315
...@@ -284,6 +284,14 @@ bool ShouldQuicMigrateSessionsEarly( ...@@ -284,6 +284,14 @@ bool ShouldQuicMigrateSessionsEarly(
GetVariationParam(quic_trial_params, "migrate_sessions_early"), "true"); GetVariationParam(quic_trial_params, "migrate_sessions_early"), "true");
} }
bool ShouldQuicAllowServerMigration(
const VariationParameters& quic_trial_params) {
return base::LowerCaseEqualsASCII(
GetVariationParam(quic_trial_params,
"allow_server_migration"),
"true");
}
size_t GetQuicMaxPacketLength(const base::CommandLine& command_line, size_t GetQuicMaxPacketLength(const base::CommandLine& command_line,
const VariationParameters& quic_trial_params) { const VariationParameters& quic_trial_params) {
if (command_line.HasSwitch(switches::kQuicMaxPacketLength)) { if (command_line.HasSwitch(switches::kQuicMaxPacketLength)) {
...@@ -394,6 +402,8 @@ void ConfigureQuicParams(const base::CommandLine& command_line, ...@@ -394,6 +402,8 @@ void ConfigureQuicParams(const base::CommandLine& command_line,
ShouldQuicMigrateSessionsOnNetworkChange(quic_trial_params); ShouldQuicMigrateSessionsOnNetworkChange(quic_trial_params);
params->quic_migrate_sessions_early = params->quic_migrate_sessions_early =
ShouldQuicMigrateSessionsEarly(quic_trial_params); ShouldQuicMigrateSessionsEarly(quic_trial_params);
params->quic_allow_server_migration =
ShouldQuicAllowServerMigration(quic_trial_params);
} }
size_t max_packet_length = size_t max_packet_length =
......
...@@ -119,6 +119,7 @@ TEST_F(NetworkSessionConfiguratorTest, EnableQuicFromFieldTrialGroup) { ...@@ -119,6 +119,7 @@ TEST_F(NetworkSessionConfiguratorTest, EnableQuicFromFieldTrialGroup) {
EXPECT_FALSE(params_.quic_disable_preconnect_if_0rtt); EXPECT_FALSE(params_.quic_disable_preconnect_if_0rtt);
EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change); EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change);
EXPECT_FALSE(params_.quic_migrate_sessions_early); EXPECT_FALSE(params_.quic_migrate_sessions_early);
EXPECT_FALSE(params_.quic_allow_server_migration);
EXPECT_TRUE(params_.quic_host_whitelist.empty()); EXPECT_TRUE(params_.quic_host_whitelist.empty());
EXPECT_FALSE(params_.quic_force_hol_blocking); EXPECT_FALSE(params_.quic_force_hol_blocking);
...@@ -258,6 +259,18 @@ TEST_F(NetworkSessionConfiguratorTest, ...@@ -258,6 +259,18 @@ TEST_F(NetworkSessionConfiguratorTest,
EXPECT_TRUE(params_.quic_migrate_sessions_early); EXPECT_TRUE(params_.quic_migrate_sessions_early);
} }
TEST_F(NetworkSessionConfiguratorTest,
QuicAllowServerMigrationFromFieldTrialParams) {
std::map<std::string, std::string> field_trial_params;
field_trial_params["allow_server_migration"] = "true";
variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params);
base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled");
ParseFieldTrials();
EXPECT_TRUE(params_.quic_allow_server_migration);
}
TEST_F(NetworkSessionConfiguratorTest, PacketLengthFromFieldTrialParams) { TEST_F(NetworkSessionConfiguratorTest, PacketLengthFromFieldTrialParams) {
std::map<std::string, std::string> field_trial_params; std::map<std::string, std::string> field_trial_params;
field_trial_params["max_packet_length"] = "1450"; field_trial_params["max_packet_length"] = "1450";
......
...@@ -127,6 +127,7 @@ HttpNetworkSession::Params::Params() ...@@ -127,6 +127,7 @@ HttpNetworkSession::Params::Params()
quic_disable_preconnect_if_0rtt(false), quic_disable_preconnect_if_0rtt(false),
quic_migrate_sessions_on_network_change(false), quic_migrate_sessions_on_network_change(false),
quic_migrate_sessions_early(false), quic_migrate_sessions_early(false),
quic_allow_server_migration(false),
quic_disable_bidirectional_streams(false), quic_disable_bidirectional_streams(false),
quic_force_hol_blocking(false), quic_force_hol_blocking(false),
proxy_delegate(NULL), proxy_delegate(NULL),
...@@ -187,6 +188,7 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) ...@@ -187,6 +188,7 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.quic_idle_connection_timeout_seconds, params.quic_idle_connection_timeout_seconds,
params.quic_migrate_sessions_on_network_change, params.quic_migrate_sessions_on_network_change,
params.quic_migrate_sessions_early, params.quic_migrate_sessions_early,
params.quic_allow_server_migration,
params.quic_force_hol_blocking, params.quic_force_hol_blocking,
params.quic_connection_options, params.quic_connection_options,
params.enable_token_binding), params.enable_token_binding),
......
...@@ -176,6 +176,9 @@ class NET_EXPORT HttpNetworkSession ...@@ -176,6 +176,9 @@ class NET_EXPORT HttpNetworkSession
// If true, active QUIC sessions experiencing poor connectivity may be // If true, active QUIC sessions experiencing poor connectivity may be
// migrated onto a new network. // migrated onto a new network.
bool quic_migrate_sessions_early; bool quic_migrate_sessions_early;
// If true, allows migration of QUIC connections to a server-specified
// alternate server address.
bool quic_allow_server_migration;
// If true, bidirectional streams over QUIC will be disabled. // If true, bidirectional streams over QUIC will be disabled.
bool quic_disable_bidirectional_streams; bool quic_disable_bidirectional_streams;
// If true, enable force HOL blocking. For measurement purposes. // If true, enable force HOL blocking. For measurement purposes.
......
...@@ -737,6 +737,15 @@ void QuicChromiumClientSession::OnClosedStream() { ...@@ -737,6 +737,15 @@ void QuicChromiumClientSession::OnClosedStream() {
} }
} }
void QuicChromiumClientSession::OnConfigNegotiated() {
QuicClientSessionBase::OnConfigNegotiated();
if (stream_factory_ && config()->HasReceivedAlternateServerAddress()) {
// Server has sent an alternate address to connect to.
stream_factory_->MigrateSessionToNewPeerAddress(
this, config()->ReceivedAlternateServerAddress(), net_log_);
}
}
void QuicChromiumClientSession::OnCryptoHandshakeEvent( void QuicChromiumClientSession::OnCryptoHandshakeEvent(
CryptoHandshakeEvent event) { CryptoHandshakeEvent event) {
if (stream_factory_ && event == HANDSHAKE_CONFIRMED && if (stream_factory_ && event == HANDSHAKE_CONFIRMED &&
......
...@@ -183,6 +183,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession ...@@ -183,6 +183,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
void OnRstStream(const QuicRstStreamFrame& frame) override; void OnRstStream(const QuicRstStreamFrame& frame) override;
// QuicClientSessionBase methods: // QuicClientSessionBase methods:
void OnConfigNegotiated() override;
void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override;
void OnProofVerifyDetailsAvailable( void OnProofVerifyDetailsAvailable(
const ProofVerifyDetails& verify_details) override; const ProofVerifyDetails& verify_details) override;
......
...@@ -29,6 +29,10 @@ QuicClientSessionBase::~QuicClientSessionBase() { ...@@ -29,6 +29,10 @@ QuicClientSessionBase::~QuicClientSessionBase() {
} }
} }
void QuicClientSessionBase::OnConfigNegotiated() {
QuicSpdySession::OnConfigNegotiated();
}
void QuicClientSessionBase::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { void QuicClientSessionBase::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
QuicSession::OnCryptoHandshakeEvent(event); QuicSession::OnCryptoHandshakeEvent(event);
} }
......
...@@ -42,6 +42,8 @@ class NET_EXPORT_PRIVATE QuicClientSessionBase ...@@ -42,6 +42,8 @@ class NET_EXPORT_PRIVATE QuicClientSessionBase
~QuicClientSessionBase() override; ~QuicClientSessionBase() override;
void OnConfigNegotiated() override;
// Override base class to set FEC policy before any data is sent by client. // Override base class to set FEC policy before any data is sent by client.
void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override; void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
......
...@@ -216,7 +216,7 @@ class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue { ...@@ -216,7 +216,7 @@ class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
}; };
// Stores IPEndPoint from CHLO or SHLO messages that are not negotiated. // Stores IPEndPoint from CHLO or SHLO messages that are not negotiated.
class QuicFixedIPEndPoint : public QuicConfigValue { class NET_EXPORT_PRIVATE QuicFixedIPEndPoint : public QuicConfigValue {
public: public:
QuicFixedIPEndPoint(QuicTag tag, QuicConfigPresence presence); QuicFixedIPEndPoint(QuicTag tag, QuicConfigPresence presence);
~QuicFixedIPEndPoint() override; ~QuicFixedIPEndPoint() override;
......
...@@ -632,6 +632,7 @@ QuicStreamFactory::QuicStreamFactory( ...@@ -632,6 +632,7 @@ QuicStreamFactory::QuicStreamFactory(
int idle_connection_timeout_seconds, int idle_connection_timeout_seconds,
bool migrate_sessions_on_network_change, bool migrate_sessions_on_network_change,
bool migrate_sessions_early, bool migrate_sessions_early,
bool allow_server_migration,
bool force_hol_blocking, bool force_hol_blocking,
const QuicTagVector& connection_options, const QuicTagVector& connection_options,
bool enable_token_binding) bool enable_token_binding)
...@@ -687,6 +688,7 @@ QuicStreamFactory::QuicStreamFactory( ...@@ -687,6 +688,7 @@ QuicStreamFactory::QuicStreamFactory(
NetworkChangeNotifier::AreNetworkHandlesSupported()), NetworkChangeNotifier::AreNetworkHandlesSupported()),
migrate_sessions_early_(migrate_sessions_early && migrate_sessions_early_(migrate_sessions_early &&
migrate_sessions_on_network_change_), migrate_sessions_on_network_change_),
allow_server_migration_(allow_server_migration),
force_hol_blocking_(force_hol_blocking), force_hol_blocking_(force_hol_blocking),
port_seed_(random_generator_->RandUint64()), port_seed_(random_generator_->RandUint64()),
check_persisted_supports_quic_(true), check_persisted_supports_quic_(true),
...@@ -1446,7 +1448,7 @@ void QuicStreamFactory::MaybeMigrateOrCloseSessions( ...@@ -1446,7 +1448,7 @@ void QuicStreamFactory::MaybeMigrateOrCloseSessions(
continue; continue;
} }
MigrateSessionToNetwork(session, new_network, bound_net_log, nullptr); MigrateSessionToNewNetwork(session, new_network, bound_net_log, nullptr);
} }
} }
...@@ -1478,15 +1480,37 @@ void QuicStreamFactory::MaybeMigrateSingleSession( ...@@ -1478,15 +1480,37 @@ void QuicStreamFactory::MaybeMigrateSingleSession(
return; return;
} }
OnSessionGoingAway(session); OnSessionGoingAway(session);
MigrateSessionToNetwork(session, new_network, scoped_event_log.net_log(), MigrateSessionToNewNetwork(session, new_network, scoped_event_log.net_log(),
packet); packet);
} }
void QuicStreamFactory::MigrateSessionToNetwork( void QuicStreamFactory::MigrateSessionToNewPeerAddress(
QuicChromiumClientSession* session, QuicChromiumClientSession* session,
NetworkHandle new_network, IPEndPoint peer_address,
const BoundNetLog& bound_net_log) {
if (!allow_server_migration_)
return;
// Specifying kInvalidNetworkHandle for the |network| parameter
// causes the session to use the default network for the new socket.
MigrateSession(session, peer_address,
NetworkChangeNotifier::kInvalidNetworkHandle, bound_net_log,
nullptr);
}
void QuicStreamFactory::MigrateSessionToNewNetwork(
QuicChromiumClientSession* session,
NetworkHandle network,
const BoundNetLog& bound_net_log, const BoundNetLog& bound_net_log,
scoped_refptr<StringIOBuffer> packet) { scoped_refptr<StringIOBuffer> packet) {
MigrateSession(session, session->connection()->peer_address(), network,
bound_net_log, packet);
}
void QuicStreamFactory::MigrateSession(QuicChromiumClientSession* session,
IPEndPoint peer_address,
NetworkHandle network,
const BoundNetLog& bound_net_log,
scoped_refptr<StringIOBuffer> packet) {
// Use OS-specified port for socket (DEFAULT_BIND) instead of // Use OS-specified port for socket (DEFAULT_BIND) instead of
// using the PortSuggester since the connection is being migrated // using the PortSuggester since the connection is being migrated
// and not being newly created. // and not being newly created.
...@@ -1494,9 +1518,7 @@ void QuicStreamFactory::MigrateSessionToNetwork( ...@@ -1494,9 +1518,7 @@ void QuicStreamFactory::MigrateSessionToNetwork(
client_socket_factory_->CreateDatagramClientSocket( client_socket_factory_->CreateDatagramClientSocket(
DatagramSocket::DEFAULT_BIND, RandIntCallback(), DatagramSocket::DEFAULT_BIND, RandIntCallback(),
session->net_log().net_log(), session->net_log().source())); session->net_log().net_log(), session->net_log().source()));
QuicConnection* connection = session->connection(); if (ConfigureSocket(socket.get(), peer_address, network) != OK) {
if (ConfigureSocket(socket.get(), connection->peer_address(), new_network) !=
OK) {
session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
HistogramAndLogMigrationFailure( HistogramAndLogMigrationFailure(
bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR, bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR,
......
...@@ -192,6 +192,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory ...@@ -192,6 +192,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
int idle_connection_timeout_seconds, int idle_connection_timeout_seconds,
bool migrate_sessions_on_network_change, bool migrate_sessions_on_network_change,
bool migrate_sessions_early, bool migrate_sessions_early,
bool allow_server_migration,
bool force_hol_blocking, bool force_hol_blocking,
const QuicTagVector& connection_options, const QuicTagVector& connection_options,
bool enable_token_binding); bool enable_token_binding);
...@@ -297,13 +298,20 @@ class NET_EXPORT_PRIVATE QuicStreamFactory ...@@ -297,13 +298,20 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
MigrationCause migration_cause, MigrationCause migration_cause,
scoped_refptr<StringIOBuffer> packet); scoped_refptr<StringIOBuffer> packet);
// Method that migrates |session| over to using |new_network|. If // Migrates |session| over to using |network|. If |network| is
// not null, |packet| is sent on the new network, else a PING frame // kInvalidNetworkHandle, default network is used. If |packet| is
// is sent. Returns ERR_QUIC_PROTOCOL_ERROR if migration fails. // not null, it is sent on the new network, else a PING frame is
void MigrateSessionToNetwork(QuicChromiumClientSession* session, // sent.
NetworkChangeNotifier::NetworkHandle new_network, void MigrateSessionToNewNetwork(QuicChromiumClientSession* session,
const BoundNetLog& bound_net_log, NetworkChangeNotifier::NetworkHandle network,
scoped_refptr<StringIOBuffer> packet); const BoundNetLog& bound_net_log,
scoped_refptr<StringIOBuffer> packet);
// Migrates |session| over to using |peer_address|. Causes a PING frame
// to be sent to the new peer address.
void MigrateSessionToNewPeerAddress(QuicChromiumClientSession* session,
IPEndPoint peer_address,
const BoundNetLog& bound_net_log);
// NetworkChangeNotifier::IPAddressObserver methods: // NetworkChangeNotifier::IPAddressObserver methods:
...@@ -447,6 +455,16 @@ class NET_EXPORT_PRIVATE QuicStreamFactory ...@@ -447,6 +455,16 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
void MaybeDisableQuic(uint16_t port); void MaybeDisableQuic(uint16_t port);
// Internal method that migrates |session| over to using
// |peer_address| and |network|. If |network| is kInvalidNetworkHandle,
// default network is used. If |packet| is not null, it is sent
// on the new network, else a PING frame is sent.
void MigrateSession(QuicChromiumClientSession* session,
IPEndPoint peer_address,
NetworkChangeNotifier::NetworkHandle network,
const BoundNetLog& bound_net_log,
scoped_refptr<StringIOBuffer> packet);
bool require_confirmation_; bool require_confirmation_;
NetLog* net_log_; NetLog* net_log_;
HostResolver* host_resolver_; HostResolver* host_resolver_;
...@@ -573,6 +591,10 @@ class NET_EXPORT_PRIVATE QuicStreamFactory ...@@ -573,6 +591,10 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// experiences poor connectivity. // experiences poor connectivity.
const bool migrate_sessions_early_; const bool migrate_sessions_early_;
// If set, allows migration of connection to server-specified alternate
// server address.
const bool allow_server_migration_;
// If set, force HOL blocking. For measurement purposes. // If set, force HOL blocking. For measurement purposes.
const bool force_hol_blocking_; const bool force_hol_blocking_;
......
...@@ -321,6 +321,7 @@ class QuicStreamFactoryTestBase { ...@@ -321,6 +321,7 @@ class QuicStreamFactoryTestBase {
idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds), idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds),
migrate_sessions_on_network_change_(false), migrate_sessions_on_network_change_(false),
migrate_sessions_early_(false), migrate_sessions_early_(false),
allow_server_migration_(false),
force_hol_blocking_(false) { force_hol_blocking_(false) {
clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
} }
...@@ -353,8 +354,8 @@ class QuicStreamFactoryTestBase { ...@@ -353,8 +354,8 @@ class QuicStreamFactoryTestBase {
close_sessions_on_ip_change_, close_sessions_on_ip_change_,
disable_quic_on_timeout_with_open_streams_, disable_quic_on_timeout_with_open_streams_,
idle_connection_timeout_seconds_, migrate_sessions_on_network_change_, idle_connection_timeout_seconds_, migrate_sessions_on_network_change_,
migrate_sessions_early_, force_hol_blocking_, QuicTagVector(), migrate_sessions_early_, allow_server_migration_, force_hol_blocking_,
/*enable_token_binding*/ false)); QuicTagVector(), /*enable_token_binding*/ false));
factory_->set_require_confirmation(false); factory_->set_require_confirmation(false);
EXPECT_FALSE(factory_->has_quic_server_info_factory()); EXPECT_FALSE(factory_->has_quic_server_info_factory());
factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory()); factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory());
...@@ -546,6 +547,7 @@ class QuicStreamFactoryTestBase { ...@@ -546,6 +547,7 @@ class QuicStreamFactoryTestBase {
int idle_connection_timeout_seconds_; int idle_connection_timeout_seconds_;
bool migrate_sessions_on_network_change_; bool migrate_sessions_on_network_change_;
bool migrate_sessions_early_; bool migrate_sessions_early_;
bool allow_server_migration_;
bool force_hol_blocking_; bool force_hol_blocking_;
}; };
...@@ -2655,6 +2657,107 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnWriteErrorMigrationDisabled) { ...@@ -2655,6 +2657,107 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnWriteErrorMigrationDisabled) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed());
} }
TEST_P(QuicStreamFactoryTest, ServerMigration) {
allow_server_migration_ = true;
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
std::unique_ptr<QuicEncryptedPacket> request_packet(
ConstructGetRequestPacket(1, kClientDataStreamId1, true, true));
MockWrite writes1[] = {MockWrite(SYNCHRONOUS, request_packet->data(),
request_packet->length(), 1)};
MockRead reads1[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
SequencedSocketData socket_data1(reads1, arraysize(reads1), writes1,
arraysize(writes1));
socket_factory_.AddSocketDataProvider(&socket_data1);
// Create request and QuicHttpStream.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(host_port_pair_, privacy_mode_,
/*cert_verify_flags=*/0, url_, "GET", net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
std::unique_ptr<QuicHttpStream> stream = request.CreateStream();
EXPECT_TRUE(stream.get());
// Cause QUIC stream to be created.
HttpRequestInfo request_info;
request_info.method = "GET";
request_info.url = GURL("https://www.example.org/");
EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY,
net_log_, CompletionCallback()));
// Ensure that session is alive and active.
QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(HasActiveSession(host_port_pair_));
// Send GET request on stream.
HttpResponseInfo response;
HttpRequestHeaders request_headers;
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
IPEndPoint ip;
session->GetDefaultSocket()->GetPeerAddress(&ip);
DVLOG(1) << "Socket connected to: " << ip.address().ToString() << " "
<< ip.port();
// Set up second socket data provider that is used after
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
std::unique_ptr<QuicEncryptedPacket> ping(
client_maker_.MakePingPacket(2, /*include_version=*/true));
std::unique_ptr<QuicEncryptedPacket> client_rst(
client_maker_.MakeAckAndRstPacket(3, false, kClientDataStreamId1,
QUIC_STREAM_CANCELLED, 1, 1, 1, true));
MockWrite writes2[] = {
MockWrite(SYNCHRONOUS, ping->data(), ping->length(), 0),
MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 3)};
std::unique_ptr<QuicEncryptedPacket> response_headers_packet(
ConstructOkResponsePacket(1, kClientDataStreamId1, false, false));
MockRead reads2[] = {MockRead(ASYNC, response_headers_packet->data(),
response_headers_packet->length(), 1),
MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
SequencedSocketData socket_data2(reads2, arraysize(reads2), writes2,
arraysize(writes2));
socket_factory_.AddSocketDataProvider(&socket_data2);
const uint8_t kTestIpAddress[] = {1, 2, 3, 4};
const uint16_t kTestPort = 123;
factory_->MigrateSessionToNewPeerAddress(
session, IPEndPoint(IPAddress(kTestIpAddress), kTestPort), net_log_);
session->GetDefaultSocket()->GetPeerAddress(&ip);
DVLOG(1) << "Socket migrated to: " << ip.address().ToString() << " "
<< ip.port();
// The session should be alive and active.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(HasActiveSession(host_port_pair_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Run the message loop so that data queued in the new socket is read by the
// packet reader.
base::RunLoop().RunUntilIdle();
// Verify that response headers on the migrated socket were delivered to the
// stream.
EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback()));
EXPECT_EQ(200, response.headers->response_code());
stream.reset();
EXPECT_TRUE(socket_data1.AllReadDataConsumed());
EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
EXPECT_TRUE(socket_data2.AllReadDataConsumed());
EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
}
TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) { TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) {
Initialize(); Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
......
...@@ -59,15 +59,21 @@ void QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams( ...@@ -59,15 +59,21 @@ void QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(
} }
// static // static
void QuicConfigPeer::SetConnectionOptionsToSend(QuicConfig* config, void QuicConfigPeer::SetConnectionOptionsToSend(QuicConfig* config,
const QuicTagVector& options) { const QuicTagVector& options) {
config->SetConnectionOptionsToSend(options); config->SetConnectionOptionsToSend(options);
} }
// static
void QuicConfigPeer::SetReceivedForceHolBlocking(QuicConfig* config) { void QuicConfigPeer::SetReceivedForceHolBlocking(QuicConfig* config) {
config->force_hol_blocking_.SetReceivedValue(1); config->force_hol_blocking_.SetReceivedValue(1);
} }
// static
void QuicConfigPeer::SetReceivedAlternateServerAddress(QuicConfig* config,
IPEndPoint addr) {
config->alternate_server_address_.SetReceivedValue(addr);
}
} // namespace test } // namespace test
} // namespace net } // namespace net
...@@ -43,6 +43,9 @@ class QuicConfigPeer { ...@@ -43,6 +43,9 @@ class QuicConfigPeer {
static void SetReceivedForceHolBlocking(QuicConfig* config); static void SetReceivedForceHolBlocking(QuicConfig* config);
static void SetReceivedAlternateServerAddress(QuicConfig* config,
IPEndPoint addr);
private: private:
DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer); DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment