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

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: Cleaning up. 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,
Ryan Hamilton 2016/09/10 16:40:34 Seems like it might just be cleaner to have this m
Jana 2016/09/10 23:08:31 Done.
1580 migration_cause != WRITE_ERROR, 1578 migration_cause != WRITE_ERROR,
1581 scoped_event_log.net_log(), packet); 1579 scoped_event_log.net_log())
1580 ? MigrationResult::SUCCESS
1581 : MigrationResult::FAILURE;
1582 } 1582 }
1583 1583
1584 void QuicStreamFactory::MigrateSessionToNewPeerAddress( 1584 void QuicStreamFactory::MigrateSessionToNewPeerAddress(
1585 QuicChromiumClientSession* session, 1585 QuicChromiumClientSession* session,
1586 IPEndPoint peer_address, 1586 IPEndPoint peer_address,
1587 const BoundNetLog& bound_net_log) { 1587 const BoundNetLog& bound_net_log) {
1588 if (!allow_server_migration_) 1588 if (!allow_server_migration_)
1589 return; 1589 return;
1590 1590
1591 IPEndPoint old_address; 1591 IPEndPoint old_address;
1592 session->GetDefaultSocket()->GetPeerAddress(&old_address); 1592 session->GetDefaultSocket()->GetPeerAddress(&old_address);
1593 DCHECK_EQ(old_address.GetFamily(), peer_address.GetFamily()); 1593 DCHECK_EQ(old_address.GetFamily(), peer_address.GetFamily());
1594 1594
1595 // Specifying kInvalidNetworkHandle for the |network| parameter 1595 // Specifying kInvalidNetworkHandle for the |network| parameter
1596 // causes the session to use the default network for the new socket. 1596 // causes the session to use the default network for the new socket.
1597 MigrateSession(session, peer_address, 1597 MigrateSessionInner(session, peer_address,
1598 NetworkChangeNotifier::kInvalidNetworkHandle, 1598 NetworkChangeNotifier::kInvalidNetworkHandle,
1599 /*close_session_on_error=*/true, bound_net_log, nullptr); 1599 /*close_session_on_error=*/true, bound_net_log);
1600 } 1600 }
1601 1601
1602 void QuicStreamFactory::MigrateSessionToNewNetwork( 1602 bool QuicStreamFactory::MigrateSessionToNewNetwork(
1603 QuicChromiumClientSession* session, 1603 QuicChromiumClientSession* session,
1604 NetworkHandle network, 1604 NetworkHandle network,
1605 bool close_session_on_error, 1605 bool close_session_on_error,
1606 const BoundNetLog& bound_net_log, 1606 const BoundNetLog& bound_net_log) {
1607 scoped_refptr<StringIOBuffer> packet) { 1607 return MigrateSessionInner(session, session->connection()->peer_address(),
1608 MigrateSession(session, session->connection()->peer_address(), network, 1608 network, close_session_on_error, bound_net_log);
1609 close_session_on_error, bound_net_log, packet);
1610 } 1609 }
1611 1610
1612 void QuicStreamFactory::MigrateSession(QuicChromiumClientSession* session, 1611 bool QuicStreamFactory::MigrateSessionInner(QuicChromiumClientSession* session,
1613 IPEndPoint peer_address, 1612 IPEndPoint peer_address,
1614 NetworkHandle network, 1613 NetworkHandle network,
1615 bool close_session_on_error, 1614 bool close_session_on_error,
1616 const BoundNetLog& bound_net_log, 1615 const BoundNetLog& bound_net_log) {
1617 scoped_refptr<StringIOBuffer> packet) {
1618 // Use OS-specified port for socket (DEFAULT_BIND) instead of 1616 // Use OS-specified port for socket (DEFAULT_BIND) instead of
1619 // using the PortSuggester since the connection is being migrated 1617 // using the PortSuggester since the connection is being migrated
1620 // and not being newly created. 1618 // and not being newly created.
1621 std::unique_ptr<DatagramClientSocket> socket( 1619 std::unique_ptr<DatagramClientSocket> socket(
1622 client_socket_factory_->CreateDatagramClientSocket( 1620 client_socket_factory_->CreateDatagramClientSocket(
1623 DatagramSocket::DEFAULT_BIND, RandIntCallback(), 1621 DatagramSocket::DEFAULT_BIND, RandIntCallback(),
1624 session->net_log().net_log(), session->net_log().source())); 1622 session->net_log().net_log(), session->net_log().source()));
1625 if (ConfigureSocket(socket.get(), peer_address, network) != OK) { 1623 if (ConfigureSocket(socket.get(), peer_address, network) != OK) {
1626 HistogramAndLogMigrationFailure( 1624 HistogramAndLogMigrationFailure(
1627 bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR, 1625 bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR,
1628 session->connection_id(), "Socket configuration failed"); 1626 session->connection_id(), "Socket configuration failed");
1629 if (close_session_on_error) { 1627 if (close_session_on_error) {
1630 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); 1628 session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR);
1631 } 1629 }
1632 return; 1630 return false;
1633 } 1631 }
1634 std::unique_ptr<QuicChromiumPacketReader> new_reader( 1632 std::unique_ptr<QuicChromiumPacketReader> new_reader(
1635 new QuicChromiumPacketReader(socket.get(), clock_.get(), session, 1633 new QuicChromiumPacketReader(socket.get(), clock_.get(), session,
1636 yield_after_packets_, yield_after_duration_, 1634 yield_after_packets_, yield_after_duration_,
1637 session->net_log())); 1635 session->net_log()));
1638 std::unique_ptr<QuicChromiumPacketWriter> new_writer( 1636 std::unique_ptr<QuicChromiumPacketWriter> new_writer(
1639 new QuicChromiumPacketWriter(socket.get())); 1637 new QuicChromiumPacketWriter(socket.get()));
1640 new_writer->set_delegate(session); 1638 new_writer->set_delegate(session);
1641 1639
1642 if (!session->MigrateToSocket(std::move(socket), std::move(new_reader), 1640 if (!session->MigrateToSocket(std::move(socket), std::move(new_reader),
1643 std::move(new_writer), packet)) { 1641 std::move(new_writer))) {
1644 // TODO(jokulik): It's not clear how we could end up on this code 1642 // 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 1643 // path. We would theoretically hit this failure if we've
1646 // performed too many migrations on this session. However, the 1644 // performed too many migrations on this session. However, the
1647 // session will be marked as going away after a previous 1645 // session will be marked as going away after a previous
1648 // migration, making subsequent migration impossible. 1646 // migration, making subsequent migration impossible.
Ryan Hamilton 2016/09/10 16:40:34 This is now reachable because of migration on writ
Jana 2016/09/10 23:08:31 Yes -- comment removed. I had thought at first tha
1649 HistogramAndLogMigrationFailure( 1647 HistogramAndLogMigrationFailure(
1650 bound_net_log, MIGRATION_STATUS_TOO_MANY_CHANGES, 1648 bound_net_log, MIGRATION_STATUS_TOO_MANY_CHANGES,
1651 session->connection_id(), "Too many migrations"); 1649 session->connection_id(), "Too many migrations");
1652 if (close_session_on_error) { 1650 if (close_session_on_error) {
1653 session->CloseSessionOnError(ERR_NETWORK_CHANGED, 1651 session->CloseSessionOnError(ERR_NETWORK_CHANGED,
1654 QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES); 1652 QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES);
1655 } 1653 }
1656 return; 1654 return false;
1657 } 1655 }
1658 HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS); 1656 HistogramMigrationStatus(MIGRATION_STATUS_SUCCESS);
1659 bound_net_log.AddEvent( 1657 bound_net_log.AddEvent(
1660 NetLog::TYPE_QUIC_CONNECTION_MIGRATION_SUCCESS, 1658 NetLog::TYPE_QUIC_CONNECTION_MIGRATION_SUCCESS,
1661 base::Bind(&NetLogQuicConnectionMigrationSuccessCallback, 1659 base::Bind(&NetLogQuicConnectionMigrationSuccessCallback,
1662 session->connection_id())); 1660 session->connection_id()));
1661 return true;
1663 } 1662 }
1664 1663
1665 void QuicStreamFactory::OnSSLConfigChanged() { 1664 void QuicStreamFactory::OnSSLConfigChanged() {
1666 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); 1665 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
1667 } 1666 }
1668 1667
1669 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { 1668 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
1670 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED); 1669 CloseAllSessions(ERR_CERT_DATABASE_CHANGED, QUIC_CONNECTION_CANCELLED);
1671 } 1670 }
1672 1671
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 // Since the session was active, there's no longer an 2052 // Since the session was active, there's no longer an
2054 // HttpStreamFactoryImpl::Job running which can mark it broken, unless the TCP 2053 // 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 2054 // 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 2055 // it as recently broken, which means that 0-RTT will be disabled but we'll
2057 // still race. 2056 // still race.
2058 http_server_properties_->MarkAlternativeServiceRecentlyBroken( 2057 http_server_properties_->MarkAlternativeServiceRecentlyBroken(
2059 alternative_service); 2058 alternative_service);
2060 } 2059 }
2061 2060
2062 } // namespace net 2061 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698