• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
6 #define QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
7 
8 #include <list>
9 #include <map>
10 #include <memory>
11 #include <vector>
12 
13 #include "absl/container/flat_hash_map.h"
14 #include "absl/strings/string_view.h"
15 #include "quiche/quic/core/http/spdy_utils.h"
16 #include "quiche/quic/platform/api/quic_mutex.h"
17 #include "quiche/quic/tools/quic_backend_response.h"
18 #include "quiche/quic/tools/quic_simple_server_backend.h"
19 #include "quiche/quic/tools/quic_url.h"
20 #include "quiche/spdy/core/http2_header_block.h"
21 #include "quiche/spdy/core/spdy_framer.h"
22 
23 namespace quic {
24 
25 // In-memory cache for HTTP responses.
26 // Reads from disk cache generated by:
27 // `wget -p --save_headers <url>`
28 class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
29  public:
30   // Class to manage loading a resource file into memory.  There are
31   // two uses: called by InitializeBackend to load resources
32   // from files, and recursively called when said resources specify
33   // server push associations.
34   class ResourceFile {
35    public:
36     explicit ResourceFile(const std::string& file_name);
37     ResourceFile(const ResourceFile&) = delete;
38     ResourceFile& operator=(const ResourceFile&) = delete;
39     virtual ~ResourceFile();
40 
41     void Read();
42 
43     // |base| is |file_name_| with |cache_directory| prefix stripped.
44     void SetHostPathFromBase(absl::string_view base);
45 
file_name()46     const std::string& file_name() { return file_name_; }
47 
host()48     absl::string_view host() { return host_; }
49 
path()50     absl::string_view path() { return path_; }
51 
spdy_headers()52     const spdy::Http2HeaderBlock& spdy_headers() { return spdy_headers_; }
53 
body()54     absl::string_view body() { return body_; }
55 
push_urls()56     const std::vector<absl::string_view>& push_urls() { return push_urls_; }
57 
58    private:
59     void HandleXOriginalUrl();
60     absl::string_view RemoveScheme(absl::string_view url);
61 
62     std::string file_name_;
63     std::string file_contents_;
64     absl::string_view body_;
65     spdy::Http2HeaderBlock spdy_headers_;
66     absl::string_view x_original_url_;
67     std::vector<absl::string_view> push_urls_;
68     std::string host_;
69     std::string path_;
70   };
71 
72   QuicMemoryCacheBackend();
73   QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete;
74   QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete;
75   ~QuicMemoryCacheBackend() override;
76 
77   // Retrieve a response from this cache for a given host and path..
78   // If no appropriate response exists, nullptr is returned.
79   const QuicBackendResponse* GetResponse(absl::string_view host,
80                                          absl::string_view path) const;
81 
82   // Adds a simple response to the cache.  The response headers will
83   // only contain the "content-length" header with the length of |body|.
84   void AddSimpleResponse(absl::string_view host, absl::string_view path,
85                          int response_code, absl::string_view body);
86 
87   // Add a simple response to the cache as AddSimpleResponse() does, and add
88   // some server push resources(resource path, corresponding response status and
89   // path) associated with it.
90   // Push resource implicitly come from the same host.
91   // TODO(b/171463363): Remove.
92   void AddSimpleResponseWithServerPushResources(
93       absl::string_view host, absl::string_view path, int response_code,
94       absl::string_view body,
95       std::list<QuicBackendResponse::ServerPushInfo> push_resources);
96 
97   // Add a response to the cache.
98   void AddResponse(absl::string_view host, absl::string_view path,
99                    spdy::Http2HeaderBlock response_headers,
100                    absl::string_view response_body);
101 
102   // Add a response, with trailers, to the cache.
103   void AddResponse(absl::string_view host, absl::string_view path,
104                    spdy::Http2HeaderBlock response_headers,
105                    absl::string_view response_body,
106                    spdy::Http2HeaderBlock response_trailers);
107 
108   // Add a response, with 103 Early Hints, to the cache.
109   void AddResponseWithEarlyHints(
110       absl::string_view host, absl::string_view path,
111       spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
112       const std::vector<spdy::Http2HeaderBlock>& early_hints);
113 
114   // Simulate a special behavior at a particular path.
115   void AddSpecialResponse(
116       absl::string_view host, absl::string_view path,
117       QuicBackendResponse::SpecialResponseType response_type);
118 
119   void AddSpecialResponse(
120       absl::string_view host, absl::string_view path,
121       spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
122       QuicBackendResponse::SpecialResponseType response_type);
123 
124   // Finds a response with the given host and path, and assign it a simulated
125   // delay. Returns true if the requisite response was found and the delay was
126   // set.
127   bool SetResponseDelay(absl::string_view host, absl::string_view path,
128                         QuicTime::Delta delay);
129 
130   // Sets a default response in case of cache misses.  Takes ownership of
131   // 'response'.
132   void AddDefaultResponse(QuicBackendResponse* response);
133 
134   // Once called, URLs which have a numeric path will send a dynamically
135   // generated response of that many bytes.
136   void GenerateDynamicResponses();
137 
138   void EnableWebTransport();
139 
140   // Find all the server push resources associated with |request_url|.
141   // TODO(b/171463363): Remove.
142   std::list<QuicBackendResponse::ServerPushInfo> GetServerPushResources(
143       std::string request_url);
144 
145   // Implements the functions for interface QuicSimpleServerBackend
146   // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
147   bool InitializeBackend(const std::string& cache_directory) override;
148   bool IsBackendInitialized() const override;
149   void FetchResponseFromBackend(
150       const spdy::Http2HeaderBlock& request_headers,
151       const std::string& request_body,
152       QuicSimpleServerBackend::RequestHandler* quic_stream) override;
153   void CloseBackendResponseStream(
154       QuicSimpleServerBackend::RequestHandler* quic_stream) override;
155   WebTransportResponse ProcessWebTransportRequest(
156       const spdy::Http2HeaderBlock& request_headers,
157       WebTransportSession* session) override;
SupportsWebTransport()158   bool SupportsWebTransport() override { return enable_webtransport_; }
159 
160  private:
161   void AddResponseImpl(absl::string_view host, absl::string_view path,
162                        QuicBackendResponse::SpecialResponseType response_type,
163                        spdy::Http2HeaderBlock response_headers,
164                        absl::string_view response_body,
165                        spdy::Http2HeaderBlock response_trailers,
166                        const std::vector<spdy::Http2HeaderBlock>& early_hints);
167 
168   std::string GetKey(absl::string_view host, absl::string_view path) const;
169 
170   // Add some server push urls with given responses for specified
171   // request if these push resources are not associated with this request yet.
172   // TODO(b/171463363): Remove.
173   void MaybeAddServerPushResources(
174       absl::string_view request_host, absl::string_view request_path,
175       std::list<QuicBackendResponse::ServerPushInfo> push_resources);
176 
177   // Check if push resource(push_host/push_path) associated with given request
178   // url already exists in server push map.
179   // TODO(b/171463363): Remove.
180   bool PushResourceExistsInCache(std::string original_request_url,
181                                  QuicBackendResponse::ServerPushInfo resource);
182 
183   // Cached responses.
184   absl::flat_hash_map<std::string, std::unique_ptr<QuicBackendResponse>>
185       responses_ QUIC_GUARDED_BY(response_mutex_);
186 
187   // The default response for cache misses, if set.
188   std::unique_ptr<QuicBackendResponse> default_response_
189       QUIC_GUARDED_BY(response_mutex_);
190 
191   // The generate bytes response, if set.
192   std::unique_ptr<QuicBackendResponse> generate_bytes_response_
193       QUIC_GUARDED_BY(response_mutex_);
194 
195   // A map from request URL to associated server push responses (if any).
196   // TODO(b/171463363): Remove.
197   std::multimap<std::string, QuicBackendResponse::ServerPushInfo>
198       server_push_resources_ QUIC_GUARDED_BY(response_mutex_);
199 
200   // Protects against concurrent access from test threads setting responses, and
201   // server threads accessing those responses.
202   mutable QuicMutex response_mutex_;
203   bool cache_initialized_;
204 
205   bool enable_webtransport_ = false;
206 };
207 
208 }  // namespace quic
209 
210 #endif  // QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
211