blob: 38d445c6006eeb142cab986129b0ff294b47ed78 [file] [log] [blame]
// 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.
#ifndef QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
#define QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
#include <list>
#include <map>
#include <memory>
#include <vector>
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mutex.h"
#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
#include "net/third_party/quiche/src/quic/tools/quic_url.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
namespace quic {
// In-memory cache for HTTP responses.
// Reads from disk cache generated by:
// `wget -p --save_headers <url>`
class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
public:
// Class to manage loading a resource file into memory. There are
// two uses: called by InitializeBackend to load resources
// from files, and recursively called when said resources specify
// server push associations.
class ResourceFile {
public:
explicit ResourceFile(const std::string& file_name);
ResourceFile(const ResourceFile&) = delete;
ResourceFile& operator=(const ResourceFile&) = delete;
virtual ~ResourceFile();
void Read();
// |base| is |file_name_| with |cache_directory| prefix stripped.
void SetHostPathFromBase(quiche::QuicheStringPiece base);
const std::string& file_name() { return file_name_; }
quiche::QuicheStringPiece host() { return host_; }
quiche::QuicheStringPiece path() { return path_; }
const spdy::SpdyHeaderBlock& spdy_headers() { return spdy_headers_; }
quiche::QuicheStringPiece body() { return body_; }
const std::vector<quiche::QuicheStringPiece>& push_urls() {
return push_urls_;
}
private:
void HandleXOriginalUrl();
quiche::QuicheStringPiece RemoveScheme(quiche::QuicheStringPiece url);
std::string file_name_;
std::string file_contents_;
quiche::QuicheStringPiece body_;
spdy::SpdyHeaderBlock spdy_headers_;
quiche::QuicheStringPiece x_original_url_;
std::vector<quiche::QuicheStringPiece> push_urls_;
std::string host_;
std::string path_;
};
QuicMemoryCacheBackend();
QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete;
QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete;
~QuicMemoryCacheBackend() override;
// Retrieve a response from this cache for a given host and path..
// If no appropriate response exists, nullptr is returned.
const QuicBackendResponse* GetResponse(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path) const;
// Adds a simple response to the cache. The response headers will
// only contain the "content-length" header with the length of |body|.
void AddSimpleResponse(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
int response_code,
quiche::QuicheStringPiece body);
// Add a simple response to the cache as AddSimpleResponse() does, and add
// some server push resources(resource path, corresponding response status and
// path) associated with it.
// Push resource implicitly come from the same host.
void AddSimpleResponseWithServerPushResources(
quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
int response_code,
quiche::QuicheStringPiece body,
std::list<QuicBackendResponse::ServerPushInfo> push_resources);
// Add a response to the cache.
void AddResponse(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
quiche::QuicheStringPiece response_body);
// Add a response, with trailers, to the cache.
void AddResponse(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
quiche::QuicheStringPiece response_body,
spdy::SpdyHeaderBlock response_trailers);
// Simulate a special behavior at a particular path.
void AddSpecialResponse(
quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
QuicBackendResponse::SpecialResponseType response_type);
void AddSpecialResponse(
quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
quiche::QuicheStringPiece response_body,
QuicBackendResponse::SpecialResponseType response_type);
void AddStopSendingResponse(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
spdy::SpdyHeaderBlock response_headers,
quiche::QuicheStringPiece response_body,
uint16_t stop_sending_code);
// Sets a default response in case of cache misses. Takes ownership of
// 'response'.
void AddDefaultResponse(QuicBackendResponse* response);
// Once called, URLs which have a numeric path will send a dynamically
// generated response of that many bytes.
void GenerateDynamicResponses();
// Find all the server push resources associated with |request_url|.
std::list<QuicBackendResponse::ServerPushInfo> GetServerPushResources(
std::string request_url);
// Implements the functions for interface QuicSimpleServerBackend
// |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
bool InitializeBackend(const std::string& cache_directory) override;
bool IsBackendInitialized() const override;
void FetchResponseFromBackend(
const spdy::SpdyHeaderBlock& request_headers,
const std::string& request_body,
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
void CloseBackendResponseStream(
QuicSimpleServerBackend::RequestHandler* quic_server_stream) override;
private:
void AddResponseImpl(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path,
QuicBackendResponse::SpecialResponseType response_type,
spdy::SpdyHeaderBlock response_headers,
quiche::QuicheStringPiece response_body,
spdy::SpdyHeaderBlock response_trailers,
uint16_t stop_sending_code);
std::string GetKey(quiche::QuicheStringPiece host,
quiche::QuicheStringPiece path) const;
// Add some server push urls with given responses for specified
// request if these push resources are not associated with this request yet.
void MaybeAddServerPushResources(
quiche::QuicheStringPiece request_host,
quiche::QuicheStringPiece request_path,
std::list<QuicBackendResponse::ServerPushInfo> push_resources);
// Check if push resource(push_host/push_path) associated with given request
// url already exists in server push map.
bool PushResourceExistsInCache(std::string original_request_url,
QuicBackendResponse::ServerPushInfo resource);
// Cached responses.
QuicUnorderedMap<std::string, std::unique_ptr<QuicBackendResponse>> responses_
QUIC_GUARDED_BY(response_mutex_);
// The default response for cache misses, if set.
std::unique_ptr<QuicBackendResponse> default_response_
QUIC_GUARDED_BY(response_mutex_);
// The generate bytes response, if set.
std::unique_ptr<QuicBackendResponse> generate_bytes_response_
QUIC_GUARDED_BY(response_mutex_);
// A map from request URL to associated server push responses (if any).
std::multimap<std::string, QuicBackendResponse::ServerPushInfo>
server_push_resources_ QUIC_GUARDED_BY(response_mutex_);
// Protects against concurrent access from test threads setting responses, and
// server threads accessing those responses.
mutable QuicMutex response_mutex_;
bool cache_initialized_;
};
} // namespace quic
#endif // QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_