Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |