Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1001)

Side by Side Diff: net/tools/quic/quic_in_memory_cache.cc

Issue 999353005: Land Recent QUIC Changes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: wrap Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/quic/quic_in_memory_cache.h ('k') | net/tools/quic/quic_in_memory_cache_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_headers.h" 12 #include "net/tools/balsa/balsa_headers.h"
13 #include "net/tools/balsa/noop_balsa_visitor.h"
14 #include "net/tools/quic/spdy_utils.h"
12 15
13 using base::FilePath; 16 using base::FilePath;
14 using base::StringPiece; 17 using base::StringPiece;
15 using std::string; 18 using std::string;
16 19
17 namespace net { 20 namespace net {
18 namespace tools { 21 namespace tools {
19 22
20 // Specifies the directory used during QuicInMemoryCache
21 // construction to seed the cache. Cache directory can be
22 // generated using `wget -p --save-headers <url>
23 string FLAGS_quic_in_memory_cache_dir = "";
24
25 namespace { 23 namespace {
26 24
27 // BalsaVisitor implementation (glue) which caches response bodies. 25 // BalsaVisitor implementation (glue) which caches response bodies.
28 class CachingBalsaVisitor : public NoOpBalsaVisitor { 26 class CachingBalsaVisitor : public NoOpBalsaVisitor {
29 public: 27 public:
30 CachingBalsaVisitor() : done_framing_(false) {} 28 CachingBalsaVisitor() : done_framing_(false) {}
31 void ProcessBodyData(const char* input, size_t size) override { 29 void ProcessBodyData(const char* input, size_t size) override {
32 AppendToBody(input, size); 30 AppendToBody(input, size);
33 } 31 }
34 void MessageDone() override { done_framing_ = true; } 32 void MessageDone() override { done_framing_ = true; }
(...skipping 10 matching lines...) Expand all
45 bool done_framing() const { return done_framing_; } 43 bool done_framing() const { return done_framing_; }
46 const string& body() const { return body_; } 44 const string& body() const { return body_; }
47 45
48 private: 46 private:
49 bool done_framing_; 47 bool done_framing_;
50 string body_; 48 string body_;
51 }; 49 };
52 50
53 } // namespace 51 } // namespace
54 52
53 QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {}
54
55 QuicInMemoryCache::Response::~Response() {}
56
55 // static 57 // static
56 QuicInMemoryCache* QuicInMemoryCache::GetInstance() { 58 QuicInMemoryCache* QuicInMemoryCache::GetInstance() {
57 return Singleton<QuicInMemoryCache>::get(); 59 return Singleton<QuicInMemoryCache>::get();
58 } 60 }
59 61
60 const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse( 62 const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
61 StringPiece host, 63 StringPiece host,
62 StringPiece path) const { 64 StringPiece path) const {
63 ResponseMap::const_iterator it = responses_.find(GetKey(host, path)); 65 ResponseMap::const_iterator it = responses_.find(GetKey(host, path));
64 if (it == responses_.end()) { 66 if (it == responses_.end()) {
65 return nullptr; 67 return nullptr;
66 } 68 }
67 return it->second; 69 return it->second;
68 } 70 }
69 71
70 void QuicInMemoryCache::AddSimpleResponse(StringPiece host, 72 void QuicInMemoryCache::AddSimpleResponse(StringPiece host,
71 StringPiece path, 73 StringPiece path,
72 int response_code, 74 int response_code,
73 StringPiece response_detail, 75 StringPiece response_detail,
74 StringPiece body) { 76 StringPiece body) {
75 BalsaHeaders response_headers; 77 SpdyHeaderBlock response_headers;
76 response_headers.SetRequestFirstlineFromStringPieces( 78 response_headers[":version"] = "HTTP/1.1";
77 "HTTP/1.1", base::IntToString(response_code), response_detail); 79 string status = base::IntToString(response_code) + " ";
78 response_headers.AppendHeader("content-length", 80 response_detail.AppendToString(&status);
79 base::IntToString(body.length())); 81 response_headers[":status"] = status;
80 82 response_headers["content-length"] = base::IntToString(body.length());
81 AddResponse(host, path, response_headers, body); 83 AddResponse(host, path, response_headers, body);
82 } 84 }
83 85
84 void QuicInMemoryCache::AddResponse(StringPiece host, 86 void QuicInMemoryCache::AddResponse(StringPiece host,
85 StringPiece path, 87 StringPiece path,
86 const BalsaHeaders& response_headers, 88 const SpdyHeaderBlock& response_headers,
87 StringPiece response_body) { 89 StringPiece response_body) {
88 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, 90 AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers,
89 response_body); 91 response_body);
90 } 92 }
91 93
92 void QuicInMemoryCache::AddSpecialResponse(StringPiece host, 94 void QuicInMemoryCache::AddSpecialResponse(StringPiece host,
93 StringPiece path, 95 StringPiece path,
94 SpecialResponseType response_type) { 96 SpecialResponseType response_type) {
95 AddResponseImpl(host, path, response_type, BalsaHeaders(), ""); 97 AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "");
96 } 98 }
97 99
98 QuicInMemoryCache::QuicInMemoryCache() { 100 QuicInMemoryCache::QuicInMemoryCache() {}
99 Initialize();
100 }
101 101
102 void QuicInMemoryCache::ResetForTests() { 102 void QuicInMemoryCache::ResetForTests() {
103 STLDeleteValues(&responses_); 103 STLDeleteValues(&responses_);
104 Initialize();
105 } 104 }
106 105
107 void QuicInMemoryCache::Initialize() { 106 void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
108 // If there's no defined cache dir, we have no initialization to do. 107 if (cache_directory.empty()) {
109 if (FLAGS_quic_in_memory_cache_dir.empty()) { 108 LOG(DFATAL) << "cache_directory must not be empty.";
110 VLOG(1) << "No cache directory found. Skipping initialization.";
111 return; 109 return;
112 } 110 }
113 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: " 111 VLOG(1) << "Attempting to initialize QuicInMemoryCache from directory: "
114 << FLAGS_quic_in_memory_cache_dir; 112 << cache_directory;
115 113 FilePath directory(cache_directory);
116 FilePath directory(FLAGS_quic_in_memory_cache_dir);
117 base::FileEnumerator file_list(directory, 114 base::FileEnumerator file_list(directory,
118 true, 115 true,
119 base::FileEnumerator::FILES); 116 base::FileEnumerator::FILES);
120 117
121 for (FilePath file = file_list.Next(); !file.empty(); 118 for (FilePath file_iter = file_list.Next(); !file_iter.empty();
122 file = file_list.Next()) { 119 file_iter = file_list.Next()) {
120 BalsaHeaders request_headers, response_headers;
123 // Need to skip files in .svn directories 121 // Need to skip files in .svn directories
124 if (file.value().find("/.svn/") != string::npos) { 122 if (file_iter.value().find("/.svn/") != string::npos) {
125 continue; 123 continue;
126 } 124 }
127 125
128 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 }
129 132
130 string file_contents; 133 string file_contents;
131 base::ReadFileToString(file, &file_contents); 134 base::ReadFileToString(file_iter, &file_contents);
132 135
133 // Frame HTTP. 136 // Frame HTTP.
134 CachingBalsaVisitor caching_visitor; 137 CachingBalsaVisitor caching_visitor;
135 BalsaFrame framer; 138 BalsaFrame framer;
136 framer.set_balsa_headers(&response_headers); 139 framer.set_balsa_headers(&response_headers);
137 framer.set_balsa_visitor(&caching_visitor); 140 framer.set_balsa_visitor(&caching_visitor);
138 size_t processed = 0; 141 size_t processed = 0;
139 while (processed < file_contents.length() && 142 while (processed < file_contents.length() &&
140 !caching_visitor.done_framing()) { 143 !caching_visitor.done_framing()) {
141 processed += framer.ProcessInput(file_contents.c_str() + processed, 144 processed += framer.ProcessInput(file_contents.c_str() + processed,
142 file_contents.length() - processed); 145 file_contents.length() - processed);
143 } 146 }
144 147
145 if (!caching_visitor.done_framing()) { 148 if (!caching_visitor.done_framing()) {
146 LOG(DFATAL) << "Did not frame entire message from file: " << file.value() 149 LOG(DFATAL) << "Did not frame entire message from file: " << file
147 << " (" << processed << " of " << file_contents.length() 150 << " (" << processed << " of " << file_contents.length()
148 << " bytes)."; 151 << " bytes).";
149 } 152 }
150 if (processed < file_contents.length()) { 153 if (processed < file_contents.length()) {
151 // Didn't frame whole file. Assume remainder is body. 154 // Didn't frame whole file. Assume remainder is body.
152 // This sometimes happens as a result of incompatibilities between 155 // This sometimes happens as a result of incompatibilities between
153 // BalsaFramer and wget's serialization of HTTP sans content-length. 156 // BalsaFramer and wget's serialization of HTTP sans content-length.
154 caching_visitor.AppendToBody(file_contents.c_str() + processed, 157 caching_visitor.AppendToBody(file_contents.c_str() + processed,
155 file_contents.length() - processed); 158 file_contents.length() - processed);
156 processed += file_contents.length(); 159 processed += file_contents.length();
157 } 160 }
158 161
159 StringPiece base = file.value(); 162 StringPiece base = file;
160 if (response_headers.HasHeader("X-Original-Url")) { 163 if (response_headers.HasHeader("X-Original-Url")) {
161 base = response_headers.GetHeader("X-Original-Url"); 164 base = response_headers.GetHeader("X-Original-Url");
162 response_headers.RemoveAllOfHeader("X-Original-Url"); 165 response_headers.RemoveAllOfHeader("X-Original-Url");
163 // 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,
164 // which is parsed properly below. 167 // which is parsed properly below.
165 if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) { 168 if (StringPieceUtils::StartsWithIgnoreCase(base, "https://")) {
166 base.remove_prefix(8); 169 base.remove_prefix(8);
167 } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) { 170 } else if (StringPieceUtils::StartsWithIgnoreCase(base, "http://")) {
168 base.remove_prefix(7); 171 base.remove_prefix(7);
169 } 172 }
170 } 173 }
171 int path_start = base.find_first_of('/'); 174 int path_start = base.find_first_of('/');
172 DCHECK_LT(0, path_start); 175 DCHECK_LT(0, path_start);
173 StringPiece host(base.substr(0, path_start)); 176 StringPiece host(base.substr(0, path_start));
174 StringPiece path(base.substr(path_start)); 177 StringPiece path(base.substr(path_start));
175 if (path[path.length() - 1] == ',') { 178 if (path[path.length() - 1] == ',') {
176 path.remove_suffix(1); 179 path.remove_suffix(1);
177 } 180 }
178 AddResponse(host, path, response_headers, caching_visitor.body()); 181 AddResponse(host, path,
182 SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers),
183 caching_visitor.body());
179 } 184 }
180 } 185 }
181 186
182 QuicInMemoryCache::~QuicInMemoryCache() { 187 QuicInMemoryCache::~QuicInMemoryCache() {
183 STLDeleteValues(&responses_); 188 STLDeleteValues(&responses_);
184 } 189 }
185 190
186 void QuicInMemoryCache::AddResponseImpl( 191 void QuicInMemoryCache::AddResponseImpl(
187 StringPiece host, 192 StringPiece host,
188 StringPiece path, 193 StringPiece path,
189 SpecialResponseType response_type, 194 SpecialResponseType response_type,
190 const BalsaHeaders& response_headers, 195 const SpdyHeaderBlock& response_headers,
191 StringPiece response_body) { 196 StringPiece response_body) {
192 string key = GetKey(host, path); 197 string key = GetKey(host, path);
193 VLOG(1) << "Adding response for: " << key; 198 VLOG(1) << "Adding response for: " << key;
194 if (ContainsKey(responses_, key)) { 199 if (ContainsKey(responses_, key)) {
195 LOG(DFATAL) << "Response for '" << key << "' already exists!"; 200 LOG(DFATAL) << "Response for '" << key << "' already exists!";
196 return; 201 return;
197 } 202 }
198 Response* new_response = new Response(); 203 Response* new_response = new Response();
199 new_response->set_response_type(response_type); 204 new_response->set_response_type(response_type);
200 new_response->set_headers(response_headers); 205 new_response->set_headers(response_headers);
201 new_response->set_body(response_body); 206 new_response->set_body(response_body);
202 responses_[key] = new_response; 207 responses_[key] = new_response;
203 } 208 }
204 209
205 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const { 210 string QuicInMemoryCache::GetKey(StringPiece host, StringPiece path) const {
206 return host.as_string() + path.as_string(); 211 return host.as_string() + path.as_string();
207 } 212 }
208 213
209 } // namespace tools 214 } // namespace tools
210 } // namespace net 215 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_in_memory_cache.h ('k') | net/tools/quic/quic_in_memory_cache_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698