OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/tools/quic/quic_in_memory_cache.h" | 5 #include "net/tools/quic/quic_in_memory_cache.h" |
6 | 6 |
7 #include "base/files/file_enumerator.h" | 7 #include "base/files/file_enumerator.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "net/tools/balsa/balsa_headers.h" | 11 #include "net/tools/balsa/balsa_headers.h" |
12 | 12 |
13 using base::FilePath; | 13 using base::FilePath; |
14 using base::StringPiece; | 14 using base::StringPiece; |
15 using std::string; | 15 using std::string; |
16 | 16 |
| 17 namespace net { |
| 18 namespace tools { |
| 19 |
17 // Specifies the directory used during QuicInMemoryCache | 20 // Specifies the directory used during QuicInMemoryCache |
18 // construction to seed the cache. Cache directory can be | 21 // construction to seed the cache. Cache directory can be |
19 // generated using `wget -p --save-headers <url> | 22 // generated using `wget -p --save-headers <url> |
20 | 23 string FLAGS_quic_in_memory_cache_dir = ""; |
21 namespace net { | |
22 namespace tools { | |
23 | |
24 std::string FLAGS_quic_in_memory_cache_dir = ""; | |
25 | 24 |
26 namespace { | 25 namespace { |
27 | 26 |
28 // BalsaVisitor implementation (glue) which caches response bodies. | 27 // BalsaVisitor implementation (glue) which caches response bodies. |
29 class CachingBalsaVisitor : public NoOpBalsaVisitor { | 28 class CachingBalsaVisitor : public NoOpBalsaVisitor { |
30 public: | 29 public: |
31 CachingBalsaVisitor() : done_framing_(false) {} | 30 CachingBalsaVisitor() : done_framing_(false) {} |
32 void ProcessBodyData(const char* input, size_t size) override { | 31 void ProcessBodyData(const char* input, size_t size) override { |
33 AppendToBody(input, size); | 32 AppendToBody(input, size); |
34 } | 33 } |
(...skipping 17 matching lines...) Expand all Loading... |
52 }; | 51 }; |
53 | 52 |
54 } // namespace | 53 } // namespace |
55 | 54 |
56 // static | 55 // static |
57 QuicInMemoryCache* QuicInMemoryCache::GetInstance() { | 56 QuicInMemoryCache* QuicInMemoryCache::GetInstance() { |
58 return Singleton<QuicInMemoryCache>::get(); | 57 return Singleton<QuicInMemoryCache>::get(); |
59 } | 58 } |
60 | 59 |
61 const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse( | 60 const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse( |
62 const BalsaHeaders& request_headers) const { | 61 StringPiece host, |
63 ResponseMap::const_iterator it = responses_.find(GetKey(request_headers)); | 62 StringPiece path) const { |
| 63 ResponseMap::const_iterator it = responses_.find(GetKey(host, path)); |
64 if (it == responses_.end()) { | 64 if (it == responses_.end()) { |
65 return nullptr; | 65 return nullptr; |
66 } | 66 } |
67 return it->second; | 67 return it->second; |
68 } | 68 } |
69 | 69 |
70 void QuicInMemoryCache::AddSimpleResponse(StringPiece method, | 70 void QuicInMemoryCache::AddSimpleResponse(StringPiece host, |
71 StringPiece path, | 71 StringPiece path, |
72 StringPiece version, | 72 int response_code, |
73 StringPiece response_code, | |
74 StringPiece response_detail, | 73 StringPiece response_detail, |
75 StringPiece body) { | 74 StringPiece body) { |
76 BalsaHeaders request_headers, response_headers; | 75 BalsaHeaders response_headers; |
77 request_headers.SetRequestFirstlineFromStringPieces(method, | 76 response_headers.SetRequestFirstlineFromStringPieces( |
78 path, | 77 "HTTP/1.1", base::IntToString(response_code), response_detail); |
79 version); | |
80 response_headers.SetRequestFirstlineFromStringPieces(version, | |
81 response_code, | |
82 response_detail); | |
83 response_headers.AppendHeader("content-length", | 78 response_headers.AppendHeader("content-length", |
84 base::IntToString(body.length())); | 79 base::IntToString(body.length())); |
85 | 80 |
86 AddResponse(request_headers, response_headers, body); | 81 AddResponse(host, path, response_headers, body); |
87 } | 82 } |
88 | 83 |
89 void QuicInMemoryCache::AddResponse(const BalsaHeaders& request_headers, | 84 void QuicInMemoryCache::AddResponse(StringPiece host, |
| 85 StringPiece path, |
90 const BalsaHeaders& response_headers, | 86 const BalsaHeaders& response_headers, |
91 StringPiece response_body) { | 87 StringPiece response_body) { |
92 VLOG(1) << "Adding response for: " << GetKey(request_headers); | 88 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, |
93 if (ContainsKey(responses_, GetKey(request_headers))) { | 89 response_body); |
94 LOG(DFATAL) << "Response for given request already exists!"; | |
95 return; | |
96 } | |
97 Response* new_response = new Response(); | |
98 new_response->set_headers(response_headers); | |
99 new_response->set_body(response_body); | |
100 responses_[GetKey(request_headers)] = new_response; | |
101 } | 90 } |
102 | 91 |
103 void QuicInMemoryCache::AddSpecialResponse(StringPiece method, | 92 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, |
104 StringPiece path, | 93 StringPiece path, |
105 StringPiece version, | |
106 SpecialResponseType response_type) { | 94 SpecialResponseType response_type) { |
107 BalsaHeaders request_headers, response_headers; | 95 AddResponseImpl(host, path, response_type, BalsaHeaders(), ""); |
108 request_headers.SetRequestFirstlineFromStringPieces(method, | |
109 path, | |
110 version); | |
111 AddResponse(request_headers, response_headers, ""); | |
112 responses_[GetKey(request_headers)]->response_type_ = response_type; | |
113 } | 96 } |
114 | 97 |
115 QuicInMemoryCache::QuicInMemoryCache() { | 98 QuicInMemoryCache::QuicInMemoryCache() { |
116 Initialize(); | 99 Initialize(); |
117 } | 100 } |
118 | 101 |
119 void QuicInMemoryCache::ResetForTests() { | 102 void QuicInMemoryCache::ResetForTests() { |
120 STLDeleteValues(&responses_); | 103 STLDeleteValues(&responses_); |
121 Initialize(); | 104 Initialize(); |
122 } | 105 } |
123 | 106 |
124 void QuicInMemoryCache::Initialize() { | 107 void QuicInMemoryCache::Initialize() { |
125 // If there's no defined cache dir, we have no initialization to do. | 108 // If there's no defined cache dir, we have no initialization to do. |
126 if (FLAGS_quic_in_memory_cache_dir.empty()) { | 109 if (FLAGS_quic_in_memory_cache_dir.empty()) { |
127 VLOG(1) << "No cache directory found. Skipping initialization."; | 110 VLOG(1) << "No cache directory found. Skipping initialization."; |
128 return; | 111 return; |
129 } | 112 } |
130 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " | 113 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " |
131 << FLAGS_quic_in_memory_cache_dir; | 114 << FLAGS_quic_in_memory_cache_dir; |
132 | 115 |
133 FilePath directory(FLAGS_quic_in_memory_cache_dir); | 116 FilePath directory(FLAGS_quic_in_memory_cache_dir); |
134 base::FileEnumerator file_list(directory, | 117 base::FileEnumerator file_list(directory, |
135 true, | 118 true, |
136 base::FileEnumerator::FILES); | 119 base::FileEnumerator::FILES); |
137 | 120 |
138 FilePath file = file_list.Next(); | 121 for (FilePath file = file_list.Next(); !file.empty(); |
139 while (!file.empty()) { | 122 file = file_list.Next()) { |
140 // Need to skip files in .svn directories | 123 // Need to skip files in .svn directories |
141 if (file.value().find("/.svn/") != std::string::npos) { | 124 if (file.value().find("/.svn/") != string::npos) { |
142 file = file_list.Next(); | |
143 continue; | 125 continue; |
144 } | 126 } |
145 | 127 |
146 BalsaHeaders request_headers, response_headers; | 128 BalsaHeaders request_headers, response_headers; |
147 | 129 |
148 string file_contents; | 130 string file_contents; |
149 base::ReadFileToString(file, &file_contents); | 131 base::ReadFileToString(file, &file_contents); |
150 | 132 |
151 // Frame HTTP. | 133 // Frame HTTP. |
152 CachingBalsaVisitor caching_visitor; | 134 CachingBalsaVisitor caching_visitor; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 base.remove_prefix(7); | 168 base.remove_prefix(7); |
187 } | 169 } |
188 } | 170 } |
189 int path_start = base.find_first_of('/'); | 171 int path_start = base.find_first_of('/'); |
190 DCHECK_LT(0, path_start); | 172 DCHECK_LT(0, path_start); |
191 StringPiece host(base.substr(0, path_start)); | 173 StringPiece host(base.substr(0, path_start)); |
192 StringPiece path(base.substr(path_start)); | 174 StringPiece path(base.substr(path_start)); |
193 if (path[path.length() - 1] == ',') { | 175 if (path[path.length() - 1] == ',') { |
194 path.remove_suffix(1); | 176 path.remove_suffix(1); |
195 } | 177 } |
196 // Set up request headers. Assume method is GET and protocol is HTTP/1.1. | 178 AddResponse(host, path, response_headers, caching_visitor.body()); |
197 request_headers.SetRequestFirstlineFromStringPieces("GET", | |
198 path, | |
199 "HTTP/1.1"); | |
200 request_headers.ReplaceOrAppendHeader("host", host); | |
201 | |
202 VLOG(1) << "Inserting 'http://" << GetKey(request_headers) | |
203 << "' into QuicInMemoryCache."; | |
204 | |
205 AddResponse(request_headers, response_headers, caching_visitor.body()); | |
206 | |
207 file = file_list.Next(); | |
208 } | 179 } |
209 } | 180 } |
210 | 181 |
211 QuicInMemoryCache::~QuicInMemoryCache() { | 182 QuicInMemoryCache::~QuicInMemoryCache() { |
212 STLDeleteValues(&responses_); | 183 STLDeleteValues(&responses_); |
213 } | 184 } |
214 | 185 |
215 string QuicInMemoryCache::GetKey(const BalsaHeaders& request_headers) const { | 186 void QuicInMemoryCache::AddResponseImpl( |
216 StringPiece uri = request_headers.request_uri(); | 187 StringPiece host, |
217 if (uri.size() == 0) { | 188 StringPiece path, |
218 return ""; | 189 SpecialResponseType response_type, |
| 190 const BalsaHeaders& response_headers, |
| 191 StringPiece response_body) { |
| 192 string key = GetKey(host, path); |
| 193 VLOG(1) << "Adding response for: " << key; |
| 194 if (ContainsKey(responses_, key)) { |
| 195 LOG(DFATAL) << "Response for '" << key << "' already exists!"; |
| 196 return; |
219 } | 197 } |
220 StringPiece host; | 198 Response* new_response = new Response(); |
221 if (uri[0] == '/') { | 199 new_response->set_response_type(response_type); |
222 host = request_headers.GetHeader("host"); | 200 new_response->set_headers(response_headers); |
223 } else if (StringPieceUtils::StartsWithIgnoreCase(uri, "https://")) { | 201 new_response->set_body(response_body); |
224 uri.remove_prefix(8); | 202 responses_[key] = new_response; |
225 } else if (StringPieceUtils::StartsWithIgnoreCase(uri, "http://")) { | 203 } |
226 uri.remove_prefix(7); | 204 |
227 } | 205 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { |
228 return host.as_string() + uri.as_string(); | 206 return host.as_string() + path.as_string(); |
229 } | 207 } |
230 | 208 |
231 } // namespace tools | 209 } // namespace tools |
232 } // namespace net | 210 } // namespace net |
OLD | NEW |