Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(564)

Side by Side Diff: net/quic/chromium/quic_stream_factory.cc

Issue 2319343004: Makes migration on write error asynchronous to avoid reentrancy issues (Closed)
Patch Set: synced and rebased Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/chromium/quic_stream_factory.h ('k') | net/quic/chromium/quic_stream_factory_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/quic/chromium/quic_stream_factory.h" 5 #include "net/quic/chromium/quic_stream_factory.h"
6 6
7 #include <openssl/aead.h> 7 #include <openssl/aead.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <tuple> 10 #include <tuple>
(...skipping 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 session->connection_id(), "Non-migratable stream"); 1542 session->connection_id(), "Non-migratable stream");
1543 if (close_if_cannot_migrate) { 1543 if (close_if_cannot_migrate) {
1544 session->CloseSessionOnError( 1544 session->CloseSessionOnError(
1545 ERR_NETWORK_CHANGED, 1545 ERR_NETWORK_CHANGED,
1546 QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM); 1546 QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM);
1547 } 1547 }
1548 continue; 1548 continue;
1549 } 1549 }
1550 1550
1551 MigrateSessionToNewNetwork(session, new_network, 1551 MigrateSessionToNewNetwork(session, new_network,
1552 /*close_session_on_error=*/true, bound_net_log, 1552 /*close_session_on_error=*/true, bound_net_log);
1553 nullptr);
1554 } 1553 }
1555 } 1554 }
1556 1555
1557 void QuicStreamFactory::MaybeMigrateSingleSession( 1556 MigrationResult QuicStreamFactory::MaybeMigrateSingleSession(
1558 QuicChromiumClientSession* session, 1557 QuicChromiumClientSession* session,
1559 MigrationCause migration_cause, 1558 MigrationCause migration_cause) {
1560 scoped_refptr<StringIOBuffer> packet) {
1561 ScopedConnectionMigrationEventLog scoped_event_log( 1559 ScopedConnectionMigrationEventLog scoped_event_log(
1562 net_log_, 1560 net_log_,
1563 migration_cause == EARLY_MIGRATION ? "EarlyMigration" : "WriteError"); 1561 migration_cause == EARLY_MIGRATION ? "EarlyMigration" : "WriteError");
1564 if (!migrate_sessions_on_network_change_ || 1562 if (!migrate_sessions_on_network_change_ ||
1565 (migration_cause == EARLY_MIGRATION && !migrate_sessions_early_) || 1563 (migration_cause == EARLY_MIGRATION && !migrate_sessions_early_) ||
1566 session->HasNonMigratableStreams() || 1564 session->HasNonMigratableStreams() ||
1567 session->config()->DisableConnectionMigration()) { 1565 session->config()->DisableConnectionMigration()) {
1568 HistogramAndLogMigrationFailure( 1566 HistogramAndLogMigrationFailure(
1569 scoped_event_log.net_log(), MIGRATION_STATUS_DISABLED, 1567 scoped_event_log.net_log(), MIGRATION_STATUS_DISABLED,
1570 session->connection_id(), "Migration disabled"); 1568 session->connection_id(), "Migration disabled");
1571 return; 1569 return MigrationResult::FAILURE;
1572 } 1570 }
1573 NetworkHandle new_network = 1571 NetworkHandle new_network =
1574 FindAlternateNetwork(session->GetDefaultSocket()->GetBoundNetwork()); 1572 FindAlternateNetwork(session->GetDefaultSocket()->GetBoundNetwork());
1575 if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) { 1573 if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
1576 // No alternate network found. 1574 // No alternate network found.
1577 HistogramAndLogMigrationFailure( 1575 HistogramAndLogMigrationFailure(
1578 scoped_event_log.net_log(), MIGRATION_STATUS_NO_ALTERNATE_NETWORK, 1576 scoped_event_log.net_log(), MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
1579 session->connection_id(), "No alternate network found"); 1577 session->connection_id(), "No alternate network found");
1580 return; 1578 return MigrationResult::NO_NEW_NETWORK;
1581 } 1579 }
1582 OnSessionGoingAway(session); 1580 OnSessionGoingAway(session);
1583 MigrateSessionToNewNetwork(session, new_network, 1581 return MigrateSessionToNewNetwork(session, new_network,
1584 migration_cause != WRITE_ERROR, 1582 migration_cause != WRITE_ERROR,
1585 scoped_event_log.net_log(), packet); 1583 scoped_event_log.net_log());
1586 } 1584 }
1587 1585
1588 void QuicStreamFactory::MigrateSessionToNewPeerAddress( 1586 void QuicStreamFactory::MigrateSessionToNewPeerAddress(
1589 QuicChromiumClientSession* session, 1587 QuicChromiumClientSession* session,
1590 IPEndPoint peer_address, 1588 IPEndPoint peer_address,
1591 const BoundNetLog& bound_net_log) { 1589 const BoundNetLog& bound_net_log) {
1592 if (!allow_server_migration_) 1590 if (!allow_server_migration_)
1593 return; 1591 return;
1594 1592
1595 IPEndPoint old_address; 1593 IPEndPoint old_address;
1596 session->GetDefaultSocket()->GetPeerAddress(&old_address); 1594 session->GetDefaultSocket()->GetPeerAddress(&old_address);
1597 DCHECK_EQ(old_address.GetFamily(), peer_address.GetFamily()); 1595 DCHECK_EQ(old_address.GetFamily(), peer_address.GetFamily());
1598 1596
1599 // Specifying kInvalidNetworkHandle for the |network| parameter 1597 // Specifying kInvalidNetworkHandle for the |network| parameter
1600 // causes the session to use the default network for the new socket. 1598 // causes the session to use the default network for the new socket.
1601 MigrateSession(session, peer_address, 1599 MigrateSessionInner(session, peer_address,
1602 NetworkChangeNotifier::kInvalidNetworkHandle, 1600 NetworkChangeNotifier::kInvalidNetworkHandle,
1603 /*close_session_on_error=*/true, bound_net_log, nullptr); 1601 /*close_session_on_error=*/true, bound_net_log);
1604 } 1602 }
1605 1603
1606 void QuicStreamFactory::MigrateSessionToNewNetwork( 1604 MigrationResult QuicStreamFactory::MigrateSessionToNewNetwork(
1607 QuicChromiumClientSession* session, 1605 QuicChromiumClientSession* session,
1608 NetworkHandle network, 1606 NetworkHandle network,
1609 bool close_session_on_error, 1607 bool close_session_on_error,
1610 const BoundNetLog& bound_net_log, 1608 const BoundNetLog& bound_net_log) {
1611 scoped_refptr<StringIOBuffer> packet) { 1609 return MigrateSessionInner(session, session->connection()->peer_address(),
1612 MigrateSession(session, session->connection()->peer_address(), network, 1610 network, close_session_on_error, bound_net_log);
1613 close_session_on_error, bound_net_log, packet);
1614 } 1611 }
1615 1612
1616 void QuicStreamFactory::MigrateSession(QuicChromiumClientSession* session, 1613 MigrationResult QuicStreamFactory::MigrateSessionInner(
1617 IPEndPoint peer_address, 1614 QuicChromiumClientSession* session,
1618 NetworkHandle network, 1615 IPEndPoint peer_address,
1619 bool close_session_on_error, 1616 NetworkHandle network,
1620 const BoundNetLog& bound_net_log, 1617 bool close_session_on_error,
1621 scoped_refptr<StringIOBuffer> packet) { 1618 const BoundNetLog& bound_net_log) {
1622 // Use OS-specified port for socket (DEFAULT_BIND) instead of 1619 // Use OS-specified port for socket (DEFAULT_BIND) instead of
1623 // using the PortSuggester since the connection is being migrated 1620 // using the PortSuggester since the connection is being migrated
1624 // and not being newly created. 1621 // and not being newly created.
1625 std::unique_ptr<DatagramClientSocket> socket( 1622 std::unique_ptr<DatagramClientSocket> socket(
1626 client_socket_factory_->CreateDatagramClientSocket( 1623 client_socket_factory_->CreateDatagramClientSocket(
1627 DatagramSocket::DEFAULT_BIND, RandIntCallback(), 1624 DatagramSocket::DEFAULT_BIND, RandIntCallback(),
1628 session->net_log().net_log(), session->net_log().source())); 1625 session->net_log().net_log(), session->net_log().source()));
1629 if (ConfigureSocket(socket.get(), peer_address, network) != OK) { 1626 if (ConfigureSocket(socket.get(), peer_address, network) != OK) {
1630 HistogramAndLogMigrationFailure( 1627 HistogramAndLogMigrationFailure(
1631 bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR, 1628 bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR,
1632 session->connection_id(), "Socket configuration failed"); 1629 session->connection_id(), "Socket configuration failed");
1633 if (close_session_on_error) { 1630 if (close_session_on_error) {
1634 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); 1631 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
1635 } 1632 }
1636 return; 1633 return MigrationResult::FAILURE;
1637 } 1634 }
1638 std::unique_ptr<QuicChromiumPacketReader> new_reader( 1635 std::unique_ptr<QuicChromiumPacketReader> new_reader(
1639 new QuicChromiumPacketReader(socket.get(), clock_.get(), session, 1636 new QuicChromiumPacketReader(socket.get(), clock_.get(), session,
1640 yield_after_packets_, yield_after_duration_, 1637 yield_after_packets_, yield_after_duration_,
1641 session->net_log())); 1638 session->net_log()));
1642 std::unique_ptr<QuicChromiumPacketWriter> new_writer( 1639 std::unique_ptr<QuicChromiumPacketWriter> new_writer(
1643 new QuicChromiumPacketWriter(socket.get())); 1640 new QuicChromiumPacketWriter(socket.get()));
1644 new_writer->set_delegate(session); 1641 new_writer->set_delegate(session);
1645 1642
1646 if (!session->MigrateToSocket(std::move(socket), std::move(new_reader), 1643 if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
1647 std::move(new_writer), packet)) { 1644 std::move(new_writer))) {
1648 // TODO(jokulik): It's not clear how we could end up on this code
1649 // path. We would theoretically hit this failure if we've
1650 // performed too many migrations on this session. However, the
1651 // session will be marked as going away after a previous
1652 // migration, making subsequent migration impossible.
1653 HistogramAndLogMigrationFailure( 1645 HistogramAndLogMigrationFailure(
1654 bound_net_log, MIGRATION_STATUS_TOO_MANY_CHANGES, 1646 bound_net_log, MIGRATION_STATUS_TOO_MANY_CHANGES,
1655 session->connection_id(), "Too many migrations"); 1647 session->connection_id(), "Too many migrations");
1656 if (close_session_on_error) { 1648 if (close_session_on_error) {
1657 session->CloseSessionOnError(ERR_NETWORK_CHANGED, 1649 session->CloseSessionOnError(ERR_NETWORK_CHANGED,
1658 QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES); 1650 QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
1659 } 1651 }
1660 return; 1652 return MigrationResult::FAILURE;
1661 } 1653 }
1662 HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS); 1654 HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
1663 bound_net_log.AddEvent( 1655 bound_net_log.AddEvent(
1664 NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS, 1656 NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS,
1665 base::Bind(&NetLogQuicConnectionMigrationSuccessCallback, 1657 base::Bind(&NetLogQuicConnectionMigrationSuccessCallback,
1666 session->connection_id())); 1658 session->connection_id()));
1659 return MigrationResult::SUCCESS;
1667 } 1660 }
1668 1661
1669 void QuicStreamFactory::OnSSLConfigChanged() { 1662 void QuicStreamFactory::OnSSLConfigChanged() {
1670 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); 1663 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
1671 } 1664 }
1672 1665
1673 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { 1666 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
1674 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); 1667 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
1675 } 1668 }
1676 1669
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
2057 // Since the session was active, there's no longer an 2050 // Since the session was active, there's no longer an
2058 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP 2051 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP
2059 // job also fails. So to avoid not using QUIC when we otherwise could, we mark 2052 // job also fails. So to avoid not using QUIC when we otherwise could, we mark
2060 // it as recently broken, which means that 0-RTT will be disabled but we'll 2053 // it as recently broken, which means that 0-RTT will be disabled but we'll
2061 // still race. 2054 // still race.
2062 http_server_properties_->MarkAlternativeServiceRecentlyBroken( 2055 http_server_properties_->MarkAlternativeServiceRecentlyBroken(
2063 alternative_service); 2056 alternative_service);
2064 } 2057 }
2065 2058
2066 } // namespace net 2059 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/chromium/quic_stream_factory.h ('k') | net/quic/chromium/quic_stream_factory_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698