xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/spdy/core/http2_header_block.h"
20 #include "quiche/spdy/core/spdy_framer.h"
21 
22 namespace quic {
23 
24 // In-memory cache for HTTP responses.
25 // Reads from disk cache generated by:
26 // `wget -p --save_headers <url>`
27 class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
28  public:
29   // Class to manage loading a resource file into memory.  There are
30   // two uses: called by InitializeBackend to load resources
31   // from files, and recursively called when said resources specify
32   // server push associations.
33   class ResourceFile {
34    public:
35     explicit ResourceFile(const std::string& file_name);
36     ResourceFile(const ResourceFile&) = delete;
37     ResourceFile& operator=(const ResourceFile&) = delete;
38     virtual ~ResourceFile();
39 
40     void Read();
41 
42     // |base| is |file_name_| with |cache_directory| prefix stripped.
43     void SetHostPathFromBase(absl::string_view base);
44 
file_name()45     const std::string& file_name() { return file_name_; }
46 
host()47     absl::string_view host() { return host_; }
48 
path()49     absl::string_view path() { return path_; }
50 
spdy_headers()51     const spdy::Http2HeaderBlock& spdy_headers() { return spdy_headers_; }
52 
body()53     absl::string_view body() { return body_; }
54 
push_urls()55     const std::vector<absl::string_view>& push_urls() { return push_urls_; }
56 
57    private:
58     void HandleXOriginalUrl();
59     absl::string_view RemoveScheme(absl::string_view url);
60 
61     std::string file_name_;
62     std::string file_contents_;
63     absl::string_view body_;
64     spdy::Http2HeaderBlock spdy_headers_;
65     absl::string_view x_original_url_;
66     std::vector<absl::string_view> push_urls_;
67     std::string host_;
68     std::string path_;
69   };
70 
71   QuicMemoryCacheBackend();
72   QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete;
73   QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete;
74   ~QuicMemoryCacheBackend() override;
75 
76   // Retrieve a response from this cache for a given host and path..
77   // If no appropriate response exists, nullptr is returned.
78   const QuicBackendResponse* GetResponse(absl::string_view host,
79                                          absl::string_view path) const;
80 
81   // Adds a simple response to the cache.  The response headers will
82   // only contain the "content-length" header with the length of |body|.
83   void AddSimpleResponse(absl::string_view host, absl::string_view path,
84                          int response_code, absl::string_view body);
85 
86   // Add a response to the cache.
87   void AddResponse(absl::string_view host, absl::string_view path,
88                    spdy::Http2HeaderBlock response_headers,
89                    absl::string_view response_body);
90 
91   // Add a response, with trailers, to the cache.
92   void AddResponse(absl::string_view host, absl::string_view path,
93                    spdy::Http2HeaderBlock response_headers,
94                    absl::string_view response_body,
95                    spdy::Http2HeaderBlock response_trailers);
96 
97   // Add a response, with 103 Early Hints, to the cache.
98   void AddResponseWithEarlyHints(
99       absl::string_view host, absl::string_view path,
100       spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
101       const std::vector<spdy::Http2HeaderBlock>& early_hints);
102 
103   // Simulate a special behavior at a particular path.
104   void AddSpecialResponse(
105       absl::string_view host, absl::string_view path,
106       QuicBackendResponse::SpecialResponseType response_type);
107 
108   void AddSpecialResponse(
109       absl::string_view host, absl::string_view path,
110       spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
111       QuicBackendResponse::SpecialResponseType response_type);
112 
113   // Finds a response with the given host and path, and assign it a simulated
114   // delay. Returns true if the requisite response was found and the delay was
115   // set.
116   bool SetResponseDelay(absl::string_view host, absl::string_view path,
117                         QuicTime::Delta delay);
118 
119   // Sets a default response in case of cache misses.  Takes ownership of
120   // 'response'.
121   void AddDefaultResponse(QuicBackendResponse* response);
122 
123   // Once called, URLs which have a numeric path will send a dynamically
124   // generated response of that many bytes.
125   void GenerateDynamicResponses();
126 
127   void EnableWebTransport();
128 
129   // Implements the functions for interface QuicSimpleServerBackend
130   // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
131   bool InitializeBackend(const std::string& cache_directory) override;
132   bool IsBackendInitialized() const override;
133   void FetchResponseFromBackend(
134       const spdy::Http2HeaderBlock& request_headers,
135       const std::string& request_body,
136       QuicSimpleServerBackend::RequestHandler* quic_stream) override;
137   void CloseBackendResponseStream(
138       QuicSimpleServerBackend::RequestHandler* quic_stream) override;
139   WebTransportResponse ProcessWebTransportRequest(
140       const spdy::Http2HeaderBlock& request_headers,
141       WebTransportSession* session) override;
SupportsWebTransport()142   bool SupportsWebTransport() override { return enable_webtransport_; }
143 
144  private:
145   void AddResponseImpl(absl::string_view host, absl::string_view path,
146                        QuicBackendResponse::SpecialResponseType response_type,
147                        spdy::Http2HeaderBlock response_headers,
148                        absl::string_view response_body,
149                        spdy::Http2HeaderBlock response_trailers,
150                        const std::vector<spdy::Http2HeaderBlock>& early_hints);
151 
152   std::string GetKey(absl::string_view host, absl::string_view path) const;
153 
154   // Cached responses.
155   absl::flat_hash_map<std::string, std::unique_ptr<QuicBackendResponse>>
156       responses_ QUIC_GUARDED_BY(response_mutex_);
157 
158   // The default response for cache misses, if set.
159   std::unique_ptr<QuicBackendResponse> default_response_
160       QUIC_GUARDED_BY(response_mutex_);
161 
162   // The generate bytes response, if set.
163   std::unique_ptr<QuicBackendResponse> generate_bytes_response_
164       QUIC_GUARDED_BY(response_mutex_);
165 
166   // Protects against concurrent access from test threads setting responses, and
167   // server threads accessing those responses.
168   mutable QuicMutex response_mutex_;
169   bool cache_initialized_;
170 
171   bool enable_webtransport_ = false;
172 };
173 
174 }  // namespace quic
175 
176 #endif  // QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
177