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

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: responses to comments 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
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 1527 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 session->connection_id(), "Non-migratable stream"); 1538 session->connection_id(), "Non-migratable stream");
1539 if (close_if_cannot_migrate) { 1539 if (close_if_cannot_migrate) {
1540 session->CloseSessionOnError( 1540 session->CloseSessionOnError(
1541 ERR_NETWORK_CHANGED, 1541 ERR_NETWORK_CHANGED,
1542 QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM); 1542 QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM);
1543 } 1543 }
1544 continue; 1544 continue;
1545 } 1545 }
1546 1546
1547 MigrateSessionToNewNetwork(session, new_network, 1547 MigrateSessionToNewNetwork(session, new_network,
1548 /*close_session_on_error=*/true, bound_net_log, 1548 /*close_session_on_error=*/true, bound_net_log);
1549 nullptr);
1550 } 1549 }
1551 } 1550 }
1552 1551
1553 void QuicStreamFactory::MaybeMigrateSingleSession( 1552 MigrationResult QuicStreamFactory::MaybeMigrateSingleSession(
1554 QuicChromiumClientSession* session, 1553 QuicChromiumClientSession* session,
1555 MigrationCause migration_cause, 1554 MigrationCause migration_cause) {
1556 scoped_refptr<StringIOBuffer> packet) {
1557 ScopedConnectionMigrationEventLog scoped_event_log( 1555 ScopedConnectionMigrationEventLog scoped_event_log(
1558 net_log_, 1556 net_log_,
1559 migration_cause == EARLY_MIGRATION ? "EarlyMigration" : "WriteError"); 1557 migration_cause == EARLY_MIGRATION ? "EarlyMigration" : "WriteError");
1560 if (!migrate_sessions_on_network_change_ || 1558 if (!migrate_sessions_on_network_change_ ||
1561 (migration_cause == EARLY_MIGRATION && !migrate_sessions_early_) || 1559 (migration_cause == EARLY_MIGRATION && !migrate_sessions_early_) ||
1562 session->HasNonMigratableStreams() || 1560 session->HasNonMigratableStreams() ||
1563 session->config()->DisableConnectionMigration()) { 1561 session->config()->DisableConnectionMigration()) {
1564 HistogramAndLogMigrationFailure( 1562 HistogramAndLogMigrationFailure(
1565 scoped_event_log.net_log(), MIGRATION_STATUS_DISABLED, 1563 scoped_event_log.net_log(), MIGRATION_STATUS_DISABLED,
1566 session->connection_id(), "Migration disabled"); 1564 session->connection_id(), "Migration disabled");
1567 return; 1565 return MigrationResult::FAILURE;
1568 } 1566 }
1569 NetworkHandle new_network = 1567 NetworkHandle new_network =
1570 FindAlternateNetwork(session->GetDefaultSocket()->GetBoundNetwork()); 1568 FindAlternateNetwork(session->GetDefaultSocket()->GetBoundNetwork());
1571 if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) { 1569 if (new_network == NetworkChangeNotifier::kInvalidNetworkHandle) {
1572 // No alternate network found. 1570 // No alternate network found.
1573 HistogramAndLogMigrationFailure( 1571 HistogramAndLogMigrationFailure(
1574 scoped_event_log.net_log(), MIGRATION_STATUS_NO_ALTERNATE_NETWORK, 1572 scoped_event_log.net_log(), MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
1575 session->connection_id(), "No alternate network found"); 1573 session->connection_id(), "No alternate network found");
1576 return; 1574 return MigrationResult::NO_NEW_NETWORK;
1577 } 1575 }
1578 OnSessionGoingAway(session); 1576 OnSessionGoingAway(session);
1579 MigrateSessionToNewNetwork(session, new_network, 1577 return MigrateSessionToNewNetwork(session, new_network,
1580 migration_cause != WRITE_ERROR, 1578 migration_cause != WRITE_ERROR,
1581 scoped_event_log.net_log(), packet); 1579 scoped_event_log.net_log());
1582 } 1580 }
1583 1581
1584 void QuicStreamFactory::MigrateSessionToNewPeerAddress( 1582 void QuicStreamFactory::MigrateSessionToNewPeerAddress(
1585 QuicChromiumClientSession* session, 1583 QuicChromiumClientSession* session,
1586 IPEndPoint peer_address, 1584 IPEndPoint peer_address,
1587 const BoundNetLog& bound_net_log) { 1585 const BoundNetLog& bound_net_log) {
1588 if (!allow_server_migration_) 1586 if (!allow_server_migration_)
1589 return; 1587 return;
1590 1588
1591 IPEndPoint old_address; 1589 IPEndPoint old_address;
1592 session->GetDefaultSocket()->GetPeerAddress(&old_address); 1590 session->GetDefaultSocket()->GetPeerAddress(&old_address);
1593 DCHECK_EQ(old_address.GetFamily(), peer_address.GetFamily()); 1591 DCHECK_EQ(old_address.GetFamily(), peer_address.GetFamily());
1594 1592
1595 // Specifying kInvalidNetworkHandle for the |network| parameter 1593 // Specifying kInvalidNetworkHandle for the |network| parameter
1596 // causes the session to use the default network for the new socket. 1594 // causes the session to use the default network for the new socket.
1597 MigrateSession(session, peer_address, 1595 MigrateSessionInner(session, peer_address,
1598 NetworkChangeNotifier::kInvalidNetworkHandle, 1596 NetworkChangeNotifier::kInvalidNetworkHandle,
1599 /*close_session_on_error=*/true, bound_net_log, nullptr); 1597 /*close_session_on_error=*/true, bound_net_log);
1600 } 1598 }
1601 1599
1602 void QuicStreamFactory::MigrateSessionToNewNetwork( 1600 MigrationResult QuicStreamFactory::MigrateSessionToNewNetwork(
1603 QuicChromiumClientSession* session, 1601 QuicChromiumClientSession* session,
1604 NetworkHandle network, 1602 NetworkHandle network,
1605 bool close_session_on_error, 1603 bool close_session_on_error,
1606 const BoundNetLog& bound_net_log, 1604 const BoundNetLog& bound_net_log) {
1607 scoped_refptr<StringIOBuffer> packet) { 1605 return MigrateSessionInner(session, session->connection()->peer_address(),
1608 MigrateSession(session, session->connection()->peer_address(), network, 1606 network, close_session_on_error, bound_net_log);
1609 close_session_on_error, bound_net_log, packet);
1610 } 1607 }
1611 1608
1612 void QuicStreamFactory::MigrateSession(QuicChromiumClientSession* session, 1609 MigrationResult QuicStreamFactory::MigrateSessionInner(
1613 IPEndPoint peer_address, 1610 QuicChromiumClientSession* session,
1614 NetworkHandle network, 1611 IPEndPoint peer_address,
1615 bool close_session_on_error, 1612 NetworkHandle network,
1616 const BoundNetLog& bound_net_log, 1613 bool close_session_on_error,
1617 scoped_refptr<StringIOBuffer> packet) { 1614 const BoundNetLog& bound_net_log) {
1618 // Use OS-specified port for socket (DEFAULT_BIND) instead of 1615 // Use OS-specified port for socket (DEFAULT_BIND) instead of
1619 // using the PortSuggester since the connection is being migrated 1616 // using the PortSuggester since the connection is being migrated
1620 // and not being newly created. 1617 // and not being newly created.
1621 std::unique_ptr<DatagramClientSocket> socket( 1618 std::unique_ptr<DatagramClientSocket> socket(
1622 client_socket_factory_->CreateDatagramClientSocket( 1619 client_socket_factory_->CreateDatagramClientSocket(
1623 DatagramSocket::DEFAULT_BIND, RandIntCallback(), 1620 DatagramSocket::DEFAULT_BIND, RandIntCallback(),
1624 session->net_log().net_log(), session->net_log().source())); 1621 session->net_log().net_log(), session->net_log().source()));
1625 if (ConfigureSocket(socket.get(), peer_address, network) != OK) { 1622 if (ConfigureSocket(socket.get(), peer_address, network) != OK) {
1626 HistogramAndLogMigrationFailure( 1623 HistogramAndLogMigrationFailure(
1627 bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR, 1624 bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR,
1628 session->connection_id(), "Socket configuration failed"); 1625 session->connection_id(), "Socket configuration failed");
1629 if (close_session_on_error) { 1626 if (close_session_on_error) {
1630 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); 1627 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
1631 } 1628 }
1632 return; 1629 return MigrationResult::FAILURE;
1633 } 1630 }
1634 std::unique_ptr<QuicChromiumPacketReader> new_reader( 1631 std::unique_ptr<QuicChromiumPacketReader> new_reader(
1635 new QuicChromiumPacketReader(socket.get(), clock_.get(), session, 1632 new QuicChromiumPacketReader(socket.get(), clock_.get(), session,
1636 yield_after_packets_, yield_after_duration_, 1633 yield_after_packets_, yield_after_duration_,
1637 session->net_log())); 1634 session->net_log()));
1638 std::unique_ptr<QuicChromiumPacketWriter> new_writer( 1635 std::unique_ptr<QuicChromiumPacketWriter> new_writer(
1639 new QuicChromiumPacketWriter(socket.get())); 1636 new QuicChromiumPacketWriter(socket.get()));
1640 new_writer->set_delegate(session); 1637 new_writer->set_delegate(session);
1641 1638
1642 if (!session->MigrateToSocket(std::move(socket), std::move(new_reader), 1639 if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
1643 std::move(new_writer), packet)) { 1640 std::move(new_writer))) {
1644 // TODO(jokulik): It's not clear how we could end up on this code
1645 // path. We would theoretically hit this failure if we've
1646 // performed too many migrations on this session. However, the
1647 // session will be marked as going away after a previous
1648 // migration, making subsequent migration impossible.
1649 HistogramAndLogMigrationFailure( 1641 HistogramAndLogMigrationFailure(
1650 bound_net_log, MIGRATION_STATUS_TOO_MANY_CHANGES, 1642 bound_net_log, MIGRATION_STATUS_TOO_MANY_CHANGES,
1651 session->connection_id(), "Too many migrations"); 1643 session->connection_id(), "Too many migrations");
1652 if (close_session_on_error) { 1644 if (close_session_on_error) {
1653 session->CloseSessionOnError(ERR_NETWORK_CHANGED, 1645 session->CloseSessionOnError(ERR_NETWORK_CHANGED,
1654 QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES); 1646 QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
1655 } 1647 }
1656 return; 1648 return MigrationResult::FAILURE;
1657 } 1649 }
1658 HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS); 1650 HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
1659 bound_net_log.AddEvent( 1651 bound_net_log.AddEvent(
1660 NetLog::TYPE_QUIC_CONNECTION_MIGRATION_SUCCESS, 1652 NetLog::TYPE_QUIC_CONNECTION_MIGRATION_SUCCESS,
1661 base::Bind(&NetLogQuicConnectionMigrationSuccessCallback, 1653 base::Bind(&NetLogQuicConnectionMigrationSuccessCallback,
1662 session->connection_id())); 1654 session->connection_id()));
1655 return MigrationResult::SUCCESS;
1663 } 1656 }
1664 1657
1665 void QuicStreamFactory::OnSSLConfigChanged() { 1658 void QuicStreamFactory::OnSSLConfigChanged() {
1666 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); 1659 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
1667 } 1660 }
1668 1661
1669 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { 1662 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
1670 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); 1663 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
1671 } 1664 }
1672 1665
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 // Since the session was active, there's no longer an 2046 // Since the session was active, there's no longer an
2054 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP 2047 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP
2055 // job also fails. So to avoid not using QUIC when we otherwise could, we mark 2048 // job also fails. So to avoid not using QUIC when we otherwise could, we mark
2056 // it as recently broken, which means that 0-RTT will be disabled but we'll 2049 // it as recently broken, which means that 0-RTT will be disabled but we'll
2057 // still race. 2050 // still race.
2058 http_server_properties_->MarkAlternativeServiceRecentlyBroken( 2051 http_server_properties_->MarkAlternativeServiceRecentlyBroken(
2059 alternative_service); 2052 alternative_service);
2060 } 2053 }
2061 2054
2062 } // namespace net 2055 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698