1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
// 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 <map>
#include <string>
#include <unordered_map>
#include "base/containers/hash_tables.h"
#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"
using base::StringPiece;
using std::string;
using std::list;
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,
const SpdyHeaderBlock& headers,
SpdyPriority priority,
string body);
ServerPushInfo(const ServerPushInfo& other);
GURL request_url;
SpdyHeaderBlock headers;
SpdyPriority priority;
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(const SpdyHeaderBlock& headers) { headers_ = headers; }
void set_trailers(const SpdyHeaderBlock& trailers) { trailers_ = 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);
StringPiece host() { return host_; }
void set_host(base::StringPiece host) { host_ = host; }
StringPiece path() { return path_; }
void set_path(base::StringPiece path) { path_ = path; }
SpdyHeaderBlock spdy_headers() { return spdy_headers_; }
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);
StringPiece RemoveScheme(base::StringPiece url);
const string cache_directory_;
const base::FilePath file_name_;
const std::string file_name_string_;
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,
const SpdyHeaderBlock& response_headers,
base::StringPiece response_body);
// Add a response, with trailers, to the cache.
void AddResponse(base::StringPiece host,
base::StringPiece path,
const SpdyHeaderBlock& response_headers,
base::StringPiece response_body,
const 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 string& cache_directory);
// Find all the server push resources associated with |request_url|.
list<ServerPushInfo> GetServerPushResources(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,
const SpdyHeaderBlock& response_headers,
base::StringPiece response_body,
const SpdyHeaderBlock& response_trailers);
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(string original_request_url,
ServerPushInfo resource);
// Cached responses.
ResponseMap responses_;
// The default response for cache misses, if set.
scoped_ptr<Response> default_response_;
// A map from request URL to associated server push responses (if any).
std::multimap<string, ServerPushInfo> server_push_resources_;
DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
};
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_IN_MEMORY_CACHE_H_
|