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_frame.h" | 11 #include "net/tools/balsa/balsa_frame.h" |
12 #include "net/tools/balsa/balsa_headers.h" | 12 #include "net/tools/balsa/balsa_headers.h" |
13 #include "net/tools/balsa/noop_balsa_visitor.h" | 13 #include "net/tools/balsa/noop_balsa_visitor.h" |
14 #include "net/tools/quic/spdy_utils.h" | 14 #include "net/tools/quic/spdy_utils.h" |
15 | 15 |
16 using base::FilePath; | 16 using base::FilePath; |
17 using base::StringPiece; | 17 using base::StringPiece; |
18 using std::string; | 18 using std::string; |
19 | 19 |
20 namespace net { | 20 namespace net { |
21 namespace tools { | 21 namespace tools { |
22 | 22 |
23 // Specifies the directory used during QuicInMemoryCache | |
24 // construction to seed the cache. Cache directory can be | |
25 // generated using `wget -p --save-headers <url> | |
26 string FLAGS_quic_in_memory_cache_dir = ""; | |
27 | |
28 namespace { | 23 namespace { |
29 | 24 |
30 // BalsaVisitor implementation (glue) which caches response bodies. | 25 // BalsaVisitor implementation (glue) which caches response bodies. |
31 class CachingBalsaVisitor : public NoOpBalsaVisitor { | 26 class CachingBalsaVisitor : public NoOpBalsaVisitor { |
32 public: | 27 public: |
33 CachingBalsaVisitor() : done_framing_(false) {} | 28 CachingBalsaVisitor() : done_framing_(false) {} |
34 void ProcessBodyData(const char* input, size_t size) override { | 29 void ProcessBodyData(const char* input, size_t size) override { |
35 AppendToBody(input, size); | 30 AppendToBody(input, size); |
36 } | 31 } |
37 void MessageDone() override { done_framing_ = true; } | 32 void MessageDone() override { done_framing_ = true; } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, | 90 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, |
96 response_body); | 91 response_body); |
97 } | 92 } |
98 | 93 |
99 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, | 94 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, |
100 StringPiece path, | 95 StringPiece path, |
101 SpecialResponseType response_type) { | 96 SpecialResponseType response_type) { |
102 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), ""); | 97 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), ""); |
103 } | 98 } |
104 | 99 |
105 QuicInMemoryCache::QuicInMemoryCache() { | 100 QuicInMemoryCache::QuicInMemoryCache() {} |
106 Initialize(); | |
107 } | |
108 | 101 |
109 void QuicInMemoryCache::ResetForTests() { | 102 void QuicInMemoryCache::ResetForTests() { |
110 STLDeleteValues(&responses_); | 103 STLDeleteValues(&responses_); |
111 Initialize(); | |
112 } | 104 } |
113 | 105 |
114 void QuicInMemoryCache::Initialize() { | 106 void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) { |
115 // If there's no defined cache dir, we have no initialization to do. | 107 if (cache_directory.empty()) { |
116 if (FLAGS_quic_in_memory_cache_dir.empty()) { | 108 LOG(DFATAL) << "cache_directory must not be empty."; |
117 VLOG(1) << "No cache directory found. Skipping initialization."; | |
118 return; | 109 return; |
119 } | 110 } |
120 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " | 111 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " |
121 << FLAGS_quic_in_memory_cache_dir; | 112 << cache_directory; |
ramant (doing other things)
2015/03/24 21:49:36
nit: indentation.
Ryan Hamilton
2015/03/24 22:03:09
Done. (In final CL)
| |
122 | 113 FilePath directory(cache_directory); |
123 FilePath directory(FLAGS_quic_in_memory_cache_dir); | |
124 base::FileEnumerator file_list(directory, | 114 base::FileEnumerator file_list(directory, |
125 true, | 115 true, |
126 base::FileEnumerator::FILES); | 116 base::FileEnumerator::FILES); |
127 | 117 |
128 for (FilePath file = file_list.Next(); !file.empty(); | 118 for (FilePath file_iter = file_list.Next(); !file_iter.empty(); |
129 file = file_list.Next()) { | 119 file_iter = file_list.Next()) { |
120 BalsaHeaders request_headers, response_headers; | |
130 // Need to skip files in .svn directories | 121 // Need to skip files in .svn directories |
131 if (file.value().find("/.svn/") != string::npos) { | 122 if (file_iter.value().find("/.svn/") != string::npos) { |
132 continue; | 123 continue; |
133 } | 124 } |
134 | 125 |
135 BalsaHeaders request_headers, response_headers; | 126 // Tease apart filename into host and path. |
127 StringPiece file(file_iter.value()); | |
128 file.remove_prefix(cache_directory.length()); | |
129 if (file[0] == '/') { | |
130 file.remove_prefix(1); | |
131 } | |
136 | 132 |
137 string file_contents; | 133 string file_contents; |
138 base::ReadFileToString(file, &file_contents); | 134 base::ReadFileToString(file_iter, &file_contents); |
139 | 135 |
140 // Frame HTTP. | 136 // Frame HTTP. |
141 CachingBalsaVisitor caching_visitor; | 137 CachingBalsaVisitor caching_visitor; |
142 BalsaFrame framer; | 138 BalsaFrame framer; |
143 framer.set_balsa_headers(&response_headers); | 139 framer.set_balsa_headers(&response_headers); |
144 framer.set_balsa_visitor(&caching_visitor); | 140 framer.set_balsa_visitor(&caching_visitor); |
145 size_t processed = 0; | 141 size_t processed = 0; |
146 while (processed < file_contents.length() && | 142 while (processed < file_contents.length() && |
147 !caching_visitor.done_framing()) { | 143 !caching_visitor.done_framing()) { |
148 processed += framer.ProcessInput(file_contents.c_str() + processed, | 144 processed += framer.ProcessInput(file_contents.c_str() + processed, |
149 file_contents.length() - processed); | 145 file_contents.length() - processed); |
150 } | 146 } |
151 | 147 |
152 if (!caching_visitor.done_framing()) { | 148 if (!caching_visitor.done_framing()) { |
153 LOG(DFATAL) << "Did not frame entire message from file: " << file.value() | 149 LOG(DFATAL) << "Did not frame entire message from file: " << file |
154 << " (" << processed << " of " << file_contents.length() | 150 << " (" << processed << " of " << file_contents.length() |
155 << " bytes)."; | 151 << " bytes)."; |
156 } | 152 } |
157 if (processed < file_contents.length()) { | 153 if (processed < file_contents.length()) { |
158 // Didn't frame whole file. Assume remainder is body. | 154 // Didn't frame whole file. Assume remainder is body. |
159 // This sometimes happens as a result of incompatibilities between | 155 // This sometimes happens as a result of incompatibilities between |
160 // BalsaFramer and wget's serialization of HTTP sans content-length. | 156 // BalsaFramer and wget's serialization of HTTP sans content-length. |
161 caching_visitor.AppendToBody(file_contents.c_str() + processed, | 157 caching_visitor.AppendToBody(file_contents.c_str() + processed, |
162 file_contents.length() - processed); | 158 file_contents.length() - processed); |
163 processed += file_contents.length(); | 159 processed += file_contents.length(); |
164 } | 160 } |
165 | 161 |
166 StringPiece base = file.value(); | 162 StringPiece base = file; |
167 if (response_headers.HasHeader("X-Original-Url")) { | 163 if (response_headers.HasHeader("X-Original-Url")) { |
168 base = response_headers.GetHeader("X-Original-Url"); | 164 base = response_headers.GetHeader("X-Original-Url"); |
169 response_headers.RemoveAllOfHeader("X-Original-Url"); | 165 response_headers.RemoveAllOfHeader("X-Original-Url"); |
170 // Remove the protocol so that the string is of the form host + path, | 166 // Remove the protocol so that the string is of the form host + path, |
171 // which is parsed properly below. | 167 // which is parsed properly below. |
172 if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) { | 168 if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) { |
173 base.remove_prefix(8); | 169 base.remove_prefix(8); |
174 } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) { | 170 } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) { |
175 base.remove_prefix(7); | 171 base.remove_prefix(7); |
176 } | 172 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 new_response->set_body(response_body); | 206 new_response->set_body(response_body); |
211 responses_[key] = new_response; | 207 responses_[key] = new_response; |
212 } | 208 } |
213 | 209 |
214 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { | 210 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { |
215 return host.as_string() + path.as_string(); | 211 return host.as_string() + path.as_string(); |
216 } | 212 } |
217 | 213 |
218 } // namespace tools | 214 } // namespace tools |
219 } // namespace net | 215 } // namespace net |
OLD | NEW |