diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc')
-rw-r--r-- | chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc | 496 |
1 files changed, 0 insertions, 496 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc deleted file mode 100644 index 19ac29a1deb..00000000000 --- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc +++ /dev/null @@ -1,496 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "quic/tools/quic_memory_cache_backend.h" - -#include <utility> - -#include "absl/strings/match.h" -#include "absl/strings/numbers.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "quic/core/http/spdy_utils.h" -#include "quic/platform/api/quic_bug_tracker.h" -#include "quic/platform/api/quic_logging.h" -#include "quic/tools/web_transport_test_visitors.h" -#include "common/platform/api/quiche_file_utils.h" -#include "common/quiche_text_utils.h" - -using spdy::Http2HeaderBlock; -using spdy::kV3LowestPriority; - -namespace quic { - -QuicMemoryCacheBackend::ResourceFile::ResourceFile(const std::string& file_name) - : file_name_(file_name) {} - -QuicMemoryCacheBackend::ResourceFile::~ResourceFile() = default; - -void QuicMemoryCacheBackend::ResourceFile::Read() { - absl::optional<std::string> maybe_file_contents = - quiche::ReadFileContents(file_name_); - if (!maybe_file_contents) { - QUIC_LOG(DFATAL) << "Failed to read file for the memory cache backend: " - << file_name_; - return; - } - file_contents_ = *maybe_file_contents; - - // First read the headers. - size_t start = 0; - while (start < file_contents_.length()) { - size_t pos = file_contents_.find('\n', start); - if (pos == std::string::npos) { - QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: " << file_name_; - return; - } - size_t len = pos - start; - // Support both dos and unix line endings for convenience. - if (file_contents_[pos - 1] == '\r') { - len -= 1; - } - absl::string_view line(file_contents_.data() + start, len); - start = pos + 1; - // Headers end with an empty line. - if (line.empty()) { - break; - } - // Extract the status from the HTTP first line. - if (line.substr(0, 4) == "HTTP") { - pos = line.find(' '); - if (pos == std::string::npos) { - QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: " - << file_name_; - return; - } - spdy_headers_[":status"] = line.substr(pos + 1, 3); - continue; - } - // Headers are "key: value". - pos = line.find(": "); - if (pos == std::string::npos) { - QUIC_LOG(DFATAL) << "Headers invalid or empty, ignoring: " << file_name_; - return; - } - spdy_headers_.AppendValueOrAddHeader( - quiche::QuicheTextUtils::ToLower(line.substr(0, pos)), - line.substr(pos + 2)); - } - - // The connection header is prohibited in HTTP/2. - spdy_headers_.erase("connection"); - - // Override the URL with the X-Original-Url header, if present. - auto it = spdy_headers_.find("x-original-url"); - if (it != spdy_headers_.end()) { - x_original_url_ = it->second; - HandleXOriginalUrl(); - } - - // X-Push-URL header is a relatively quick way to support sever push - // in the toy server. A production server should use link=preload - // stuff as described in https://w3c.github.io/preload/. - it = spdy_headers_.find("x-push-url"); - if (it != spdy_headers_.end()) { - absl::string_view push_urls = it->second; - size_t start = 0; - while (start < push_urls.length()) { - size_t pos = push_urls.find('\0', start); - if (pos == std::string::npos) { - push_urls_.push_back(absl::string_view(push_urls.data() + start, - push_urls.length() - start)); - break; - } - push_urls_.push_back(absl::string_view(push_urls.data() + start, pos)); - start += pos + 1; - } - } - - body_ = absl::string_view(file_contents_.data() + start, - file_contents_.size() - start); -} - -void QuicMemoryCacheBackend::ResourceFile::SetHostPathFromBase( - absl::string_view base) { - QUICHE_DCHECK(base[0] != '/') << base; - size_t path_start = base.find_first_of('/'); - if (path_start == absl::string_view::npos) { - host_ = std::string(base); - path_ = ""; - return; - } - - host_ = std::string(base.substr(0, path_start)); - size_t query_start = base.find_first_of(','); - if (query_start > 0) { - path_ = std::string(base.substr(path_start, query_start - 1)); - } else { - path_ = std::string(base.substr(path_start)); - } -} - -absl::string_view QuicMemoryCacheBackend::ResourceFile::RemoveScheme( - absl::string_view url) { - if (absl::StartsWith(url, "https://")) { - url.remove_prefix(8); - } else if (absl::StartsWith(url, "http://")) { - url.remove_prefix(7); - } - return url; -} - -void QuicMemoryCacheBackend::ResourceFile::HandleXOriginalUrl() { - absl::string_view url(x_original_url_); - SetHostPathFromBase(RemoveScheme(url)); -} - -const QuicBackendResponse* QuicMemoryCacheBackend::GetResponse( - absl::string_view host, absl::string_view path) const { - QuicWriterMutexLock lock(&response_mutex_); - - auto it = responses_.find(GetKey(host, path)); - if (it == responses_.end()) { - uint64_t ignored = 0; - if (generate_bytes_response_) { - if (absl::SimpleAtoi(absl::string_view(path.data() + 1, path.size() - 1), - &ignored)) { - // The actual parsed length is ignored here and will be recomputed - // by the caller. - return generate_bytes_response_.get(); - } - } - QUIC_DVLOG(1) << "Get response for resource failed: host " << host - << " path " << path; - if (default_response_) { - return default_response_.get(); - } - return nullptr; - } - return it->second.get(); -} - -using ServerPushInfo = QuicBackendResponse::ServerPushInfo; -using SpecialResponseType = QuicBackendResponse::SpecialResponseType; - -void QuicMemoryCacheBackend::AddSimpleResponse(absl::string_view host, - absl::string_view path, - int response_code, - absl::string_view body) { - Http2HeaderBlock response_headers; - response_headers[":status"] = absl::StrCat(response_code); - response_headers["content-length"] = absl::StrCat(body.length()); - AddResponse(host, path, std::move(response_headers), body); -} - -void QuicMemoryCacheBackend::AddSimpleResponseWithServerPushResources( - absl::string_view host, absl::string_view path, int response_code, - absl::string_view body, std::list<ServerPushInfo> push_resources) { - AddSimpleResponse(host, path, response_code, body); - MaybeAddServerPushResources(host, path, push_resources); -} - -void QuicMemoryCacheBackend::AddDefaultResponse(QuicBackendResponse* response) { - QuicWriterMutexLock lock(&response_mutex_); - default_response_.reset(response); -} - -void QuicMemoryCacheBackend::AddResponse(absl::string_view host, - absl::string_view path, - Http2HeaderBlock response_headers, - absl::string_view response_body) { - AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE, - std::move(response_headers), response_body, - Http2HeaderBlock(), std::vector<spdy::Http2HeaderBlock>()); -} - -void QuicMemoryCacheBackend::AddResponse(absl::string_view host, - absl::string_view path, - Http2HeaderBlock response_headers, - absl::string_view response_body, - Http2HeaderBlock response_trailers) { - AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE, - std::move(response_headers), response_body, - std::move(response_trailers), - std::vector<spdy::Http2HeaderBlock>()); -} - -void QuicMemoryCacheBackend::AddResponseWithEarlyHints( - absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, absl::string_view response_body, - const std::vector<spdy::Http2HeaderBlock>& early_hints) { - AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE, - std::move(response_headers), response_body, - Http2HeaderBlock(), early_hints); -} - -void QuicMemoryCacheBackend::AddSpecialResponse( - absl::string_view host, absl::string_view path, - SpecialResponseType response_type) { - AddResponseImpl(host, path, response_type, Http2HeaderBlock(), "", - Http2HeaderBlock(), std::vector<spdy::Http2HeaderBlock>()); -} - -void QuicMemoryCacheBackend::AddSpecialResponse( - absl::string_view host, absl::string_view path, - spdy::Http2HeaderBlock response_headers, absl::string_view response_body, - SpecialResponseType response_type) { - AddResponseImpl(host, path, response_type, std::move(response_headers), - response_body, Http2HeaderBlock(), - std::vector<spdy::Http2HeaderBlock>()); -} - -QuicMemoryCacheBackend::QuicMemoryCacheBackend() : cache_initialized_(false) {} - -bool QuicMemoryCacheBackend::InitializeBackend( - const std::string& cache_directory) { - if (cache_directory.empty()) { - QUIC_BUG(quic_bug_10932_1) << "cache_directory must not be empty."; - return false; - } - QUIC_LOG(INFO) - << "Attempting to initialize QuicMemoryCacheBackend from directory: " - << cache_directory; - std::vector<std::string> files; - if (!quiche::EnumerateDirectoryRecursively(cache_directory, files)) { - QUIC_BUG(QuicMemoryCacheBackend unreadable directory) - << "Can't read QuicMemoryCacheBackend directory: " << cache_directory; - return false; - } - std::list<std::unique_ptr<ResourceFile>> resource_files; - for (const auto& filename : files) { - std::unique_ptr<ResourceFile> resource_file(new ResourceFile(filename)); - - // Tease apart filename into host and path. - std::string base(resource_file->file_name()); - // Transform windows path separators to URL path separators. - for (size_t i = 0; i < base.length(); ++i) { - if (base[i] == '\\') { - base[i] = '/'; - } - } - base.erase(0, cache_directory.length()); - if (base[0] == '/') { - base.erase(0, 1); - } - - resource_file->SetHostPathFromBase(base); - resource_file->Read(); - - AddResponse(resource_file->host(), resource_file->path(), - resource_file->spdy_headers().Clone(), resource_file->body()); - - resource_files.push_back(std::move(resource_file)); - } - - for (const auto& resource_file : resource_files) { - std::list<ServerPushInfo> push_resources; - for (const auto& push_url : resource_file->push_urls()) { - QuicUrl url(push_url); - const QuicBackendResponse* response = GetResponse(url.host(), url.path()); - if (!response) { - QUIC_BUG(quic_bug_10932_2) - << "Push URL '" << push_url << "' not found."; - return false; - } - push_resources.push_back(ServerPushInfo(url, response->headers().Clone(), - kV3LowestPriority, - (std::string(response->body())))); - } - MaybeAddServerPushResources(resource_file->host(), resource_file->path(), - push_resources); - } - - cache_initialized_ = true; - return true; -} - -void QuicMemoryCacheBackend::GenerateDynamicResponses() { - QuicWriterMutexLock lock(&response_mutex_); - // Add a generate bytes response. - spdy::Http2HeaderBlock response_headers; - response_headers[":status"] = "200"; - generate_bytes_response_ = std::make_unique<QuicBackendResponse>(); - generate_bytes_response_->set_headers(std::move(response_headers)); - generate_bytes_response_->set_response_type( - QuicBackendResponse::GENERATE_BYTES); -} - -void QuicMemoryCacheBackend::EnableWebTransport() { - enable_webtransport_ = true; -} - -bool QuicMemoryCacheBackend::IsBackendInitialized() const { - return cache_initialized_; -} - -void QuicMemoryCacheBackend::FetchResponseFromBackend( - const Http2HeaderBlock& request_headers, - const std::string& /*request_body*/, - QuicSimpleServerBackend::RequestHandler* quic_stream) { - const QuicBackendResponse* quic_response = nullptr; - // Find response in cache. If not found, send error response. - auto authority = request_headers.find(":authority"); - auto path = request_headers.find(":path"); - if (authority != request_headers.end() && path != request_headers.end()) { - quic_response = GetResponse(authority->second, path->second); - } - - std::string request_url; - if (authority != request_headers.end()) { - request_url = std::string(authority->second); - } - if (path != request_headers.end()) { - request_url += std::string(path->second); - } - QUIC_DVLOG(1) - << "Fetching QUIC response from backend in-memory cache for url " - << request_url; - quic_stream->OnResponseBackendComplete(quic_response); -} - -// The memory cache does not have a per-stream handler -void QuicMemoryCacheBackend::CloseBackendResponseStream( - QuicSimpleServerBackend::RequestHandler* /*quic_stream*/) {} - -std::list<ServerPushInfo> QuicMemoryCacheBackend::GetServerPushResources( - std::string request_url) { - QuicWriterMutexLock lock(&response_mutex_); - - std::list<ServerPushInfo> resources; - auto resource_range = server_push_resources_.equal_range(request_url); - for (auto it = resource_range.first; it != resource_range.second; ++it) { - resources.push_back(it->second); - } - QUIC_DVLOG(1) << "Found " << resources.size() << " push resources for " - << request_url; - return resources; -} - -QuicMemoryCacheBackend::WebTransportResponse -QuicMemoryCacheBackend::ProcessWebTransportRequest( - const spdy::Http2HeaderBlock& request_headers, - WebTransportSession* session) { - if (!SupportsWebTransport()) { - return QuicSimpleServerBackend::ProcessWebTransportRequest(request_headers, - session); - } - - auto path_it = request_headers.find(":path"); - if (path_it == request_headers.end()) { - WebTransportResponse response; - response.response_headers[":status"] = "400"; - return response; - } - absl::string_view path = path_it->second; - if (path == "/echo") { - WebTransportResponse response; - response.response_headers[":status"] = "200"; - response.visitor = - std::make_unique<EchoWebTransportSessionVisitor>(session); - return response; - } - - WebTransportResponse response; - response.response_headers[":status"] = "404"; - return response; -} - -QuicMemoryCacheBackend::~QuicMemoryCacheBackend() { - { - QuicWriterMutexLock lock(&response_mutex_); - responses_.clear(); - } -} - -void QuicMemoryCacheBackend::AddResponseImpl( - absl::string_view host, absl::string_view path, - SpecialResponseType response_type, Http2HeaderBlock response_headers, - absl::string_view response_body, Http2HeaderBlock response_trailers, - const std::vector<spdy::Http2HeaderBlock>& early_hints) { - QuicWriterMutexLock lock(&response_mutex_); - - QUICHE_DCHECK(!host.empty()) - << "Host must be populated, e.g. \"www.google.com\""; - std::string key = GetKey(host, path); - if (responses_.contains(key)) { - QUIC_BUG(quic_bug_10932_3) - << "Response for '" << key << "' already exists!"; - return; - } - auto new_response = std::make_unique<QuicBackendResponse>(); - new_response->set_response_type(response_type); - new_response->set_headers(std::move(response_headers)); - new_response->set_body(response_body); - new_response->set_trailers(std::move(response_trailers)); - for (auto& headers : early_hints) { - new_response->AddEarlyHints(headers); - } - QUIC_DVLOG(1) << "Add response with key " << key; - responses_[key] = std::move(new_response); -} - -std::string QuicMemoryCacheBackend::GetKey(absl::string_view host, - absl::string_view path) const { - std::string host_string = std::string(host); - size_t port = host_string.find(':'); - if (port != std::string::npos) - host_string = std::string(host_string.c_str(), port); - return host_string + std::string(path); -} - -void QuicMemoryCacheBackend::MaybeAddServerPushResources( - absl::string_view request_host, absl::string_view request_path, - std::list<ServerPushInfo> push_resources) { - std::string request_url = GetKey(request_host, request_path); - - for (const auto& push_resource : push_resources) { - if (PushResourceExistsInCache(request_url, push_resource)) { - continue; - } - - QUIC_DVLOG(1) << "Add request-resource association: request url " - << request_url << " push url " - << push_resource.request_url.ToString() - << " response headers " - << push_resource.headers.DebugString(); - { - QuicWriterMutexLock lock(&response_mutex_); - server_push_resources_.insert(std::make_pair(request_url, push_resource)); - } - std::string host = push_resource.request_url.host(); - if (host.empty()) { - host = std::string(request_host); - } - std::string path = push_resource.request_url.path(); - bool found_existing_response = false; - { - QuicWriterMutexLock lock(&response_mutex_); - found_existing_response = responses_.contains(GetKey(host, path)); - } - if (!found_existing_response) { - // Add a server push response to responses map, if it is not in the map. - absl::string_view body = push_resource.body; - QUIC_DVLOG(1) << "Add response for push resource: host " << host - << " path " << path; - AddResponse(host, path, push_resource.headers.Clone(), body); - } - } -} - -bool QuicMemoryCacheBackend::PushResourceExistsInCache( - std::string original_request_url, ServerPushInfo resource) { - QuicWriterMutexLock lock(&response_mutex_); - auto resource_range = - server_push_resources_.equal_range(original_request_url); - for (auto it = resource_range.first; it != resource_range.second; ++it) { - ServerPushInfo push_resource = it->second; - if (push_resource.request_url.ToString() == - resource.request_url.ToString()) { - return true; - } - } - return false; -} - -} // namespace quic |