| // 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 NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_ |
| #define NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_ |
| |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/macros.h" |
| #include "base/memory/singleton.h" |
| #include "base/strings/string_piece.h" |
| #include "net/http/http_response_headers.h" |
| #include "net/quic/spdy_utils.h" |
| #include "net/spdy/spdy_framer.h" |
| #include "url/gurl.h" |
| |
| namespace base { |
| |
| template <typename Type> |
| struct DefaultSingletonTraits; |
| |
| } // namespace base |
| |
| namespace net { |
| |
| namespace test { |
| class QuicInMemoryCachePeer; |
| } // namespace test |
| |
| class QuicServer; |
| |
| // In-memory cache for HTTP responses. |
| // Reads from disk cache generated by: |
| // `wget -p --save_headers <url>` |
| class QuicInMemoryCache { |
| public: |
| // A ServerPushInfo contains path of the push request and everything needed in |
| // comprising a response for the push request. |
| struct ServerPushInfo { |
| ServerPushInfo(GURL request_url, |
| SpdyHeaderBlock headers, |
| SpdyPriority priority, |
| std::string body); |
| ServerPushInfo(const ServerPushInfo& other); |
| GURL request_url; |
| SpdyHeaderBlock headers; |
| SpdyPriority priority; |
| std::string body; |
| }; |
| |
| enum SpecialResponseType { |
| REGULAR_RESPONSE, // Send the headers and body like a server should. |
| CLOSE_CONNECTION, // Close the connection (sending the close packet). |
| IGNORE_REQUEST, // Do nothing, expect the client to time out. |
| }; |
| |
| // Container for response header/body pairs. |
| class Response { |
| public: |
| Response(); |
| ~Response(); |
| |
| SpecialResponseType response_type() const { return response_type_; } |
| const SpdyHeaderBlock& headers() const { return headers_; } |
| const SpdyHeaderBlock& trailers() const { return trailers_; } |
| const base::StringPiece body() const { return base::StringPiece(body_); } |
| |
| void set_response_type(SpecialResponseType response_type) { |
| response_type_ = response_type; |
| } |
| void set_headers(SpdyHeaderBlock headers) { headers_ = std::move(headers); } |
| void set_trailers(SpdyHeaderBlock trailers) { |
| trailers_ = std::move(trailers); |
| } |
| void set_body(base::StringPiece body) { body.CopyToString(&body_); } |
| |
| private: |
| SpecialResponseType response_type_; |
| SpdyHeaderBlock headers_; |
| SpdyHeaderBlock trailers_; |
| std::string body_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Response); |
| }; |
| |
| // Class to manage loading a resource file into memory. There are |
| // two uses: called by InitializeFromDirectory to load resources |
| // from files, and recursively called when said resources specify |
| // server push associations. |
| class ResourceFile { |
| public: |
| explicit ResourceFile(const base::FilePath& file_name); |
| virtual ~ResourceFile(); |
| |
| // abstract: implementation details are chromium and internal |
| // version specific. |
| virtual void Read() = 0; |
| void SetHostPathFromBase(base::StringPiece base); |
| |
| base::StringPiece host() { return host_; } |
| void set_host(base::StringPiece host) { host_ = host; } |
| |
| base::StringPiece path() { return path_; } |
| void set_path(base::StringPiece path) { path_ = path; } |
| |
| const SpdyHeaderBlock& spdy_headers() { return spdy_headers_; } |
| |
| base::StringPiece body() { return body_; } |
| |
| const std::vector<base::StringPiece>& push_urls() { return push_urls_; } |
| |
| const std::string& file_name() { return file_name_string_; } |
| |
| protected: |
| void HandleXOriginalUrl(); |
| void HandlePushUrls(const std::vector<base::StringPiece>& push_urls); |
| base::StringPiece RemoveScheme(base::StringPiece url); |
| |
| const std::string cache_directory_; |
| const base::FilePath file_name_; |
| const std::string file_name_string_; |
| std::string file_contents_; |
| base::StringPiece body_; |
| SpdyHeaderBlock spdy_headers_; |
| base::StringPiece x_original_url_; |
| std::vector<base::StringPiece> push_urls_; |
| |
| private: |
| base::StringPiece host_; |
| base::StringPiece path_; |
| QuicInMemoryCache* cache_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ResourceFile); |
| }; |
| |
| // Returns the singleton instance of the cache. |
| static QuicInMemoryCache* GetInstance(); |
| |
| // Retrieve a response from this cache for a given host and path.. |
| // If no appropriate response exists, nullptr is returned. |
| const Response* GetResponse(base::StringPiece host, |
| base::StringPiece 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(base::StringPiece host, |
| base::StringPiece path, |
| int response_code, |
| base::StringPiece 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( |
| base::StringPiece host, |
| base::StringPiece path, |
| int response_code, |
| base::StringPiece body, |
| std::list<ServerPushInfo> push_resources); |
| |
| // Add a response to the cache. |
| void AddResponse(base::StringPiece host, |
| base::StringPiece path, |
| SpdyHeaderBlock response_headers, |
| base::StringPiece response_body); |
| |
| // Add a response, with trailers, to the cache. |
| void AddResponse(base::StringPiece host, |
| base::StringPiece path, |
| SpdyHeaderBlock response_headers, |
| base::StringPiece response_body, |
| SpdyHeaderBlock response_trailers); |
| |
| // Simulate a special behavior at a particular path. |
| void AddSpecialResponse(base::StringPiece host, |
| base::StringPiece path, |
| SpecialResponseType response_type); |
| |
| // Sets a default response in case of cache misses. Takes ownership of |
| // 'response'. |
| void AddDefaultResponse(Response* response); |
| |
| // |cache_cirectory| can be generated using `wget -p --save-headers <url>`. |
| void InitializeFromDirectory(const std::string& cache_directory); |
| |
| // Find all the server push resources associated with |request_url|. |
| std::list<ServerPushInfo> GetServerPushResources(std::string request_url); |
| |
| private: |
| typedef std::unordered_map<std::string, Response*> ResponseMap; |
| |
| friend struct base::DefaultSingletonTraits<QuicInMemoryCache>; |
| friend class test::QuicInMemoryCachePeer; |
| |
| QuicInMemoryCache(); |
| ~QuicInMemoryCache(); |
| |
| void ResetForTests(); |
| |
| void AddResponseImpl(base::StringPiece host, |
| base::StringPiece path, |
| SpecialResponseType response_type, |
| SpdyHeaderBlock response_headers, |
| base::StringPiece response_body, |
| SpdyHeaderBlock response_trailers); |
| |
| std::string GetKey(base::StringPiece host, base::StringPiece 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(base::StringPiece request_host, |
| base::StringPiece request_path, |
| std::list<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, |
| ServerPushInfo resource); |
| |
| // Cached responses. |
| ResponseMap responses_; |
| |
| // The default response for cache misses, if set. |
| std::unique_ptr<Response> default_response_; |
| |
| // A map from request URL to associated server push responses (if any). |
| std::multimap<std::string, ServerPushInfo> server_push_resources_; |
| |
| DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache); |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_ |