Commit c7255f01 authored by Renjie Tang's avatar Renjie Tang Committed by Commit Bot

Complete the implementation of QuicClientSessionCache to allow multiple TLS...

Complete the implementation of QuicClientSessionCache to allow multiple TLS session ticket for a single QUIC session.

Change-Id: Iff6bbcb74708ac0584662273c0ad01162b597a98
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2155165Reviewed-by: default avatarNick Harper <nharper@chromium.org>
Commit-Queue: Renjie Tang <renjietang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#761149}
parent af14fc18
...@@ -4340,9 +4340,7 @@ test("net_unittests") { ...@@ -4340,9 +4340,7 @@ test("net_unittests") {
"quic/quic_chromium_client_session_test.cc", "quic/quic_chromium_client_session_test.cc",
"quic/quic_chromium_client_stream_test.cc", "quic/quic_chromium_client_stream_test.cc",
"quic/quic_chromium_connection_helper_test.cc", "quic/quic_chromium_connection_helper_test.cc",
"quic/quic_client_session_cache_unittests.cc",
# Temporarily disabled due to version reordering.
# "quic/quic_client_session_cache_unittests.cc",
"quic/quic_clock_skew_detector_test.cc", "quic/quic_clock_skew_detector_test.cc",
"quic/quic_connectivity_probing_manager_test.cc", "quic/quic_connectivity_probing_manager_test.cc",
"quic/quic_end_to_end_unittest.cc", "quic/quic_end_to_end_unittest.cc",
......
...@@ -12,20 +12,31 @@ namespace net { ...@@ -12,20 +12,31 @@ namespace net {
namespace { namespace {
const size_t kDefaultMaxEntries = 1024; const size_t kDefaultMaxEntries = 1024;
// Check whether the SSL session inside |state| is expired at |now|. // Returns false if the SSL |session| doesn't exist or it is expired at |now|.
bool IsExpired(quic::QuicResumptionState* state, time_t now) { bool IsValid(SSL_SESSION* session, time_t now) {
if (!session)
return false;
if (now < 0) if (now < 0)
return true; return false;
SSL_SESSION* session = state->tls_session.get();
uint64_t now_u64 = static_cast<uint64_t>(now); uint64_t now_u64 = static_cast<uint64_t>(now);
// now_u64 may be slightly behind because of differences in how // now_u64 may be slightly behind because of differences in how
// time is calculated at this layer versus BoringSSL. // time is calculated at this layer versus BoringSSL.
// Add a second of wiggle room to account for this. // Add a second of wiggle room to account for this.
return now_u64 < SSL_SESSION_get_time(session) - 1 || return !(now_u64 < SSL_SESSION_get_time(session) - 1 ||
now_u64 >= now_u64 >= SSL_SESSION_get_time(session) +
SSL_SESSION_get_time(session) + SSL_SESSION_get_timeout(session); SSL_SESSION_get_timeout(session));
}
bool DoApplicationStatesMatch(quic::ApplicationState* state,
quic::ApplicationState* other) {
if ((state && !other) || (!state && other))
return false;
if ((!state && !other) || *state == *other)
return true;
return false;
} }
} // namespace } // namespace
...@@ -47,11 +58,29 @@ QuicClientSessionCache::~QuicClientSessionCache() { ...@@ -47,11 +58,29 @@ QuicClientSessionCache::~QuicClientSessionCache() {
void QuicClientSessionCache::Insert(const quic::QuicServerId& server_id, void QuicClientSessionCache::Insert(const quic::QuicServerId& server_id,
bssl::UniquePtr<SSL_SESSION> session, bssl::UniquePtr<SSL_SESSION> session,
quic::TransportParameters* params, quic::TransportParameters* params,
std::vector<uint8_t>* application_states) { quic::ApplicationState* application_state) {
auto state = std::make_unique<quic::QuicResumptionState>(); DCHECK(session) << "TLS session is not inserted into client cache.";
state->tls_session = std::move(session); DCHECK(params) << "Transport Parameters is not inserted into client cache.";
// TODO: Do something with TransportParams and application_states. auto iter = cache_.Get(server_id);
cache_.Put(server_id, std::move(state)); if (iter == cache_.end()) {
CreateAndInsertEntry(server_id, std::move(session), params,
application_state);
return;
}
DCHECK(iter->second.params);
// The states are both the same, so only need to insert sessions.
if (*params == *iter->second.params &&
DoApplicationStatesMatch(application_state,
iter->second.application_state.get())) {
iter->second.PushSession(std::move(session));
return;
}
// Erase the existing entry because this Insert call must come from a
// different QUIC session.
cache_.Erase(iter);
CreateAndInsertEntry(server_id, std::move(session), params,
application_state);
} }
std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup( std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup(
...@@ -62,18 +91,23 @@ std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup( ...@@ -62,18 +91,23 @@ std::unique_ptr<quic::QuicResumptionState> QuicClientSessionCache::Lookup(
return nullptr; return nullptr;
time_t now = clock_->Now().ToTimeT(); time_t now = clock_->Now().ToTimeT();
std::unique_ptr<quic::QuicResumptionState> state = std::move(iter->second); if (!IsValid(iter->second.PeekSession(), now)) {
cache_.Erase(iter); cache_.Erase(iter);
if (IsExpired(state.get(), now)) return nullptr;
state = nullptr; }
auto state = std::make_unique<quic::QuicResumptionState>();
state->tls_session = iter->second.PopSession();
state->transport_params = iter->second.params.get();
state->application_state = iter->second.application_state.get();
return state; return state;
} }
void QuicClientSessionCache::FlushExpiredStates() { void QuicClientSessionCache::FlushInvalidEntries() {
time_t now = clock_->Now().ToTimeT(); time_t now = clock_->Now().ToTimeT();
auto iter = cache_.begin(); auto iter = cache_.begin();
while (iter != cache_.end()) { while (iter != cache_.end()) {
if (IsExpired(iter->second.get(), now)) { if (!IsValid(iter->second.PeekSession(), now)) {
iter = cache_.Erase(iter); iter = cache_.Erase(iter);
} else { } else {
++iter; ++iter;
...@@ -87,7 +121,7 @@ void QuicClientSessionCache::OnMemoryPressure( ...@@ -87,7 +121,7 @@ void QuicClientSessionCache::OnMemoryPressure(
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
break; break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
FlushExpiredStates(); FlushInvalidEntries();
break; break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
Flush(); Flush();
...@@ -95,4 +129,48 @@ void QuicClientSessionCache::OnMemoryPressure( ...@@ -95,4 +129,48 @@ void QuicClientSessionCache::OnMemoryPressure(
} }
} }
void QuicClientSessionCache::Flush() {
cache_.Clear();
}
void QuicClientSessionCache::CreateAndInsertEntry(
const quic::QuicServerId& server_id,
bssl::UniquePtr<SSL_SESSION> session,
quic::TransportParameters* params,
quic::ApplicationState* application_state) {
Entry entry;
entry.PushSession(std::move(session));
entry.params = std::make_unique<quic::TransportParameters>(*params);
if (application_state) {
entry.application_state =
std::make_unique<quic::ApplicationState>(*application_state);
}
cache_.Put(server_id, std::move(entry));
}
QuicClientSessionCache::Entry::Entry() = default;
QuicClientSessionCache::Entry::Entry(Entry&&) = default;
QuicClientSessionCache::Entry::~Entry() = default;
void QuicClientSessionCache::Entry::PushSession(
bssl::UniquePtr<SSL_SESSION> session) {
if (sessions[0] != nullptr) {
sessions[1] = std::move(sessions[0]);
}
sessions[0] = std::move(session);
}
bssl::UniquePtr<SSL_SESSION> QuicClientSessionCache::Entry::PopSession() {
if (sessions[0] == nullptr)
return nullptr;
bssl::UniquePtr<SSL_SESSION> session = std::move(sessions[0]);
sessions[0] = std::move(sessions[1]);
sessions[1] = nullptr;
return session;
}
SSL_SESSION* QuicClientSessionCache::Entry::PeekSession() {
return sessions[0].get();
}
} // namespace net } // namespace net
...@@ -33,7 +33,7 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache { ...@@ -33,7 +33,7 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache {
void Insert(const quic::QuicServerId& server_id, void Insert(const quic::QuicServerId& server_id,
bssl::UniquePtr<SSL_SESSION> session, bssl::UniquePtr<SSL_SESSION> session,
quic::TransportParameters* params, quic::TransportParameters* params,
std::vector<uint8_t>* application_states) override; quic::ApplicationState* application_state) override;
std::unique_ptr<quic::QuicResumptionState> Lookup( std::unique_ptr<quic::QuicResumptionState> Lookup(
const quic::QuicServerId& server_id, const quic::QuicServerId& server_id,
...@@ -43,17 +43,40 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache { ...@@ -43,17 +43,40 @@ class NET_EXPORT_PRIVATE QuicClientSessionCache : public quic::SessionCache {
size_t size() const { return cache_.size(); } size_t size() const { return cache_.size(); }
void Flush() { cache_.Clear(); } void Flush();
void OnMemoryPressure( void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
private: private:
void FlushExpiredStates(); struct Entry {
Entry();
Entry(Entry&&);
~Entry();
// Adds a new |session| onto sessions, dropping the oldest one if two are
// already stored.
void PushSession(bssl::UniquePtr<SSL_SESSION> session);
// Retrieves the latest session from the entry, meanwhile removing it.
bssl::UniquePtr<SSL_SESSION> PopSession();
SSL_SESSION* PeekSession();
bssl::UniquePtr<SSL_SESSION> sessions[2];
std::unique_ptr<quic::TransportParameters> params;
std::unique_ptr<quic::ApplicationState> application_state;
};
void FlushInvalidEntries();
// Creates a new entry and insert into |cache_|.
void CreateAndInsertEntry(const quic::QuicServerId& server_id,
bssl::UniquePtr<SSL_SESSION> session,
quic::TransportParameters* params,
quic::ApplicationState* application_state);
base::Clock* clock_; base::Clock* clock_;
base::MRUCache<quic::QuicServerId, std::unique_ptr<quic::QuicResumptionState>> base::MRUCache<quic::QuicServerId, Entry> cache_;
cache_;
std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
}; };
......
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