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

Side by Side Diff: components/certificate_transparency/log_proof_fetcher.cc

Issue 1405293009: Certificate Transparency: Fetching consistency proofs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Design, documentation fixes Created 4 years, 11 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/certificate_transparency/log_proof_fetcher.h" 5 #include "components/certificate_transparency/log_proof_fetcher.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 8
9 #include "base/callback_helpers.h"
10 #include "base/format_macros.h"
9 #include "base/logging.h" 11 #include "base/logging.h"
10 #include "base/memory/ref_counted.h" 12 #include "base/memory/ref_counted.h"
13 #include "base/numerics/safe_conversions.h"
11 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
12 #include "base/values.h" 16 #include "base/values.h"
13 #include "components/safe_json/safe_json_parser.h" 17 #include "components/safe_json/safe_json_parser.h"
14 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
15 #include "net/base/load_flags.h" 19 #include "net/base/load_flags.h"
16 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
17 #include "net/base/request_priority.h" 21 #include "net/base/request_priority.h"
18 #include "net/cert/ct_log_response_parser.h" 22 #include "net/cert/ct_log_response_parser.h"
19 #include "net/cert/signed_tree_head.h" 23 #include "net/cert/signed_tree_head.h"
20 #include "net/http/http_status_code.h" 24 #include "net/http/http_status_code.h"
25 #include "net/url_request/url_request.h"
21 #include "net/url_request/url_request_context.h" 26 #include "net/url_request/url_request_context.h"
22 #include "url/gurl.h" 27 #include "url/gurl.h"
23 28
24 namespace certificate_transparency { 29 namespace certificate_transparency {
25 30
26 namespace { 31 namespace {
27 32
28 // Shamelessly copied from domain_reliability/util.cc 33 // Class for issuing a particular request from a CT log and assembling the
29 int GetNetErrorFromURLRequestStatus(const net::URLRequestStatus& status) { 34 // response.
30 switch (status.status()) { 35 // Creates the URLRequest instance for fetching the URL from the log
31 case net::URLRequestStatus::SUCCESS: 36 // (supplied as |request_url| in the c'tor) and implements the
32 return net::OK; 37 // URLRequest::Delegate interface for assembling the response.
33 case net::URLRequestStatus::CANCELED: 38 class LogFetcher : public net::URLRequest::Delegate {
34 return net::ERR_ABORTED; 39 public:
35 case net::URLRequestStatus::FAILED: 40 using FailureCallback = base::Callback<void(int, int)>;
36 return status.error(); 41
37 default: 42 LogFetcher(net::URLRequestContext* request_context,
38 NOTREACHED(); 43 const GURL& request_url,
39 return net::ERR_FAILED; 44 const base::Closure& success_callback,
40 } 45 const FailureCallback& failure_callback);
46 ~LogFetcher() override {}
47
48 // net::URLRequest::Delegate
49 void OnResponseStarted(net::URLRequest* request) override;
50 void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
51
52 const std::string& assembled_response() const { return assembled_response_; }
53
54 private:
55 // Handles the final result of a URLRequest::Read call on the request.
56 // Returns true if another read should be started, false if the read
57 // failed completely or we have to wait for OnResponseStarted to
58 // be called.
59 bool HandleReadResult(int bytes_read);
60
61 // Calls URLRequest::Read on |request| repeatedly, until HandleReadResult
62 // indicates it should no longer be called. Usually this would be when there
63 // is pending IO that requires waiting for OnResponseStarted to be called.
64 void StartNextReadLoop();
65
66 // Invokes the success callback. After this method is called, the LogFetcher
67 // is deleted and no longer safe to call.
68 void RequestComplete();
69
70 // Invokes the failure callback with the supplied error information.
71 // After this method the LogFetcher is deleted and no longer safe to call.
72 void InvokeFailureCallback(int net_error, int http_response_code);
73
74 scoped_ptr<net::URLRequest> url_request_;
75 const GURL request_url_;
76 base::Closure success_callback_;
77 FailureCallback failure_callback_;
78 scoped_refptr<net::IOBufferWithSize> response_buffer_;
79 std::string assembled_response_;
80
81 DISALLOW_COPY_AND_ASSIGN(LogFetcher);
82 };
83
84 LogFetcher::LogFetcher(net::URLRequestContext* request_context,
85 const GURL& request_url,
86 const base::Closure& success_callback,
87 const FailureCallback& failure_callback)
88 : request_url_(request_url),
89 success_callback_(success_callback),
90 failure_callback_(failure_callback) {
91 DCHECK(request_url_.SchemeIsHTTPOrHTTPS());
92 url_request_ =
93 request_context->CreateRequest(request_url_, net::DEFAULT_PRIORITY, this);
94 // This request should not send any cookies or otherwise identifying data,
95 // as CT logs are expected to be publicly-accessible and connections to them
96 // stateless.
97 url_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
98 net::LOAD_DO_NOT_SAVE_COOKIES |
99 net::LOAD_DO_NOT_SEND_AUTH_DATA);
100
101 url_request_->Start();
102 }
103
104 void LogFetcher::OnResponseStarted(net::URLRequest* request) {
105 DCHECK_EQ(url_request_.get(), request);
106 int http_response_code = request->GetResponseCode();
107
108 if (!request->status().is_success()) {
109 InvokeFailureCallback(request->status().error(), http_response_code);
110 return;
111 }
112
113 if (http_response_code != net::HTTP_OK) {
114 InvokeFailureCallback(net::OK, http_response_code);
115 return;
116 }
117
118 // Lazily initialize |response_buffer_| to avoid consuming memory until an
119 // actual response has been received.
120 if (!response_buffer_) {
121 response_buffer_ =
122 new net::IOBufferWithSize(LogProofFetcher::kMaxLogResponseSizeInBytes);
123 }
124
125 StartNextReadLoop();
126 }
127
128 void LogFetcher::OnReadCompleted(net::URLRequest* request, int bytes_read) {
129 DCHECK_EQ(url_request_.get(), request);
130
131 if (HandleReadResult(bytes_read))
132 StartNextReadLoop();
133 }
134
135 bool LogFetcher::HandleReadResult(int bytes_read) {
136 // Start by checking for an error condition.
137 // If there are errors, invoke the failure callback and clean up the
138 // request.
139 if (!url_request_->status().is_success() || bytes_read < 0) {
140 int net_error = url_request_->status().error();
141 if (bytes_read < 0)
142 net_error = net::URLRequestStatus::FAILED;
mmenke 2016/01/25 17:41:39 If bytes_read is < 0, net_error really should indi
Eran Messeri 2016/01/25 19:20:22 Done.
143
144 InvokeFailureCallback(net_error, net::OK);
mmenke 2016/01/25 17:41:39 BUG: net::OK -> net::HTTP_OK. Should have a test
Eran Messeri 2016/01/25 19:20:22 I've added assertions in the test that the http_re
145 return false;
146 }
147
148 // Not an error, but no data available, so wait for OnReadCompleted
149 // callback.
150 if (url_request_->status().is_io_pending())
151 return false;
152
153 // Nothing more to read from the stream - finish handling the response.
154 if (bytes_read == 0) {
155 RequestComplete();
156 return false;
157 }
158
159 // We have data, collect it and indicate another read is needed.
160 DCHECK_GE(bytes_read, 0);
161 // |bytes_read| is non-negative at this point, casting to size_t should be
162 // safe.
163 if (base::checked_cast<size_t>(bytes_read) >
164 LogProofFetcher::kMaxLogResponseSizeInBytes ||
165 LogProofFetcher::kMaxLogResponseSizeInBytes <
166 (assembled_response_.size() + bytes_read)) {
167 // Log response is too big, invoke the failure callback.
168 InvokeFailureCallback(net::ERR_FILE_TOO_BIG, net::HTTP_OK);
169 return false;
170 }
171
172 assembled_response_.append(response_buffer_->data(), bytes_read);
173 return true;
174 }
175
176 void LogFetcher::StartNextReadLoop() {
177 bool continue_reading = true;
178 while (continue_reading) {
179 int read_bytes = 0;
180 url_request_->Read(response_buffer_.get(), response_buffer_->size(),
181 &read_bytes);
182 continue_reading = HandleReadResult(read_bytes);
183 }
184 }
185
186 void LogFetcher::RequestComplete() {
187 // Get rid of the buffer as it really isn't necessary.
188 response_buffer_ = nullptr;
189 base::ResetAndReturn(&success_callback_).Run();
190 // NOTE: |this| is not valid after invoking the callback, as the LogFetcher
191 // instance will be deleted by the callback.
192 }
193
194 void LogFetcher::InvokeFailureCallback(int net_error, int http_response_code) {
195 base::ResetAndReturn(&failure_callback_).Run(net_error, http_response_code);
196 // NOTE: |this| is not valid after this callback, as the LogFetcher instance
197 // invoking the callback will be deleted by the callback.
41 } 198 }
42 199
43 } // namespace 200 } // namespace
44 201
45 struct LogProofFetcher::FetchState { 202 // Interface for handling the response from a CT log for a particular
46 FetchState(const std::string& log_id, 203 // request.
47 const SignedTreeHeadFetchedCallback& fetched_callback, 204 // All log responses are JSON and should be parsed; however the response
48 const FetchFailedCallback& failed_callback); 205 // to each request should be parsed and validated differently.
49 ~FetchState(); 206 //
50 207 // LogResponseHandler instances should be deleted by the |done_callback| when
51 std::string log_id; 208 // it is invoked.
52 SignedTreeHeadFetchedCallback fetched_callback; 209 class LogResponseHandler {
53 FetchFailedCallback failed_callback; 210 public:
54 scoped_refptr<net::IOBufferWithSize> response_buffer; 211 using DoneCallback = base::Callback<void(const base::Closure&)>;
55 std::string assembled_response; 212
213 // |log_id| will be passed to the |failure_callback| to indicate which log
214 // failures pretain to.
215 LogResponseHandler(
216 const std::string& log_id,
217 const LogProofFetcher::FetchFailedCallback& failure_callback);
218 virtual ~LogResponseHandler();
219
220 // Starts the actual fetching from the URL, storing |done_callback| for
221 // invocation when fetching and parsing of the request finished.
222 // It is safe, and expected, to delete this object in the |done_callback|.
223 void StartFetch(net::URLRequestContext* request_context,
224 const GURL& request_url,
225 const DoneCallback& done_callback);
226
227 // Handle successful fetch by the LogFetcher (by parsing the JSON and
228 // handing the parsed JSON to HandleParsedJson, which is request-specific).
229 void HandleFetchCompletion();
230
231 // Handle network failure to complete the request to the log, by invoking
232 // the |done_callback_|.
233 virtual void HandleNetFailure(int net_error, int http_response_code);
234
235 protected:
236 // Handle successful parsing of JSON by invoking HandleParsedJson, then
237 // invoking the |done_callback_| with the returned Closure.
238 void OnJsonParseSuccess(scoped_ptr<base::Value> parsed_json);
239
240 // Handle failure to parse the JSON by invoking HandleJsonParseFailure, then
241 // invoking the |done_callback_| with the returned Closure.
242 void OnJsonParseError(const std::string& error);
243
244 // Handle respones JSON that parsed successfully, usually by
245 // returning the success callback bound to parsed values as a Closure.
246 virtual base::Closure HandleParsedJson(const base::Value& parsed_json) = 0;
247
248 // Handle failure to parse response JSON, usually by returning the failure
249 // callback bound to a request-specific net error code.
250 virtual base::Closure HandleJsonParseFailure(
251 const std::string& json_error) = 0;
252
253 const std::string log_id_;
254 LogProofFetcher::FetchFailedCallback failure_callback_;
255 scoped_ptr<LogFetcher> fetcher_;
256 DoneCallback done_callback_;
257
258 base::WeakPtrFactory<LogResponseHandler> weak_factory_;
56 }; 259 };
57 260
58 LogProofFetcher::FetchState::FetchState( 261 LogResponseHandler::LogResponseHandler(
59 const std::string& log_id, 262 const std::string& log_id,
60 const SignedTreeHeadFetchedCallback& fetched_callback, 263 const LogProofFetcher::FetchFailedCallback& failure_callback)
61 const FetchFailedCallback& failed_callback) 264 : log_id_(log_id),
62 : log_id(log_id), 265 failure_callback_(failure_callback),
63 fetched_callback(fetched_callback), 266 fetcher_(nullptr),
64 failed_callback(failed_callback), 267 weak_factory_(this) {
65 response_buffer(new net::IOBufferWithSize(kMaxLogResponseSizeInBytes)) {} 268 DCHECK(!failure_callback_.is_null());
66 269 }
67 LogProofFetcher::FetchState::~FetchState() {} 270
271 LogResponseHandler::~LogResponseHandler() {}
272
273 void LogResponseHandler::StartFetch(net::URLRequestContext* request_context,
274 const GURL& request_url,
275 const DoneCallback& done_callback) {
276 done_callback_ = done_callback;
277 fetcher_.reset(
278 new LogFetcher(request_context, request_url,
279 base::Bind(&LogResponseHandler::HandleFetchCompletion,
280 weak_factory_.GetWeakPtr()),
281 base::Bind(&LogResponseHandler::HandleNetFailure,
282 weak_factory_.GetWeakPtr())));
283 }
284
285 void LogResponseHandler::HandleFetchCompletion() {
286 safe_json::SafeJsonParser::Parse(
287 fetcher_->assembled_response(),
288 base::Bind(&LogResponseHandler::OnJsonParseSuccess,
289 weak_factory_.GetWeakPtr()),
290 base::Bind(&LogResponseHandler::OnJsonParseError,
291 weak_factory_.GetWeakPtr()));
292
293 // The assembled_response string is copied into the SafeJsonParser so it
294 // is safe to get rid of the object that owns it.
295 fetcher_.reset();
296 }
297
298 void LogResponseHandler::HandleNetFailure(int net_error,
299 int http_response_code) {
300 fetcher_.reset();
301 LogProofFetcher::FetchFailedCallback failure_callback =
302 base::ResetAndReturn(&failure_callback_);
303
304 base::ResetAndReturn(&done_callback_)
305 .Run(
306 base::Bind(failure_callback, log_id_, net_error, http_response_code));
307 // NOTE: |this| is not valid after the |done_callback_| is invoked.
308 }
309
310 void LogResponseHandler::OnJsonParseSuccess(
311 scoped_ptr<base::Value> parsed_json) {
312 base::ResetAndReturn(&done_callback_).Run(HandleParsedJson(*parsed_json));
313 // NOTE: |this| is not valid after the |done_callback_| is invoked.
314 }
315
316 void LogResponseHandler::OnJsonParseError(const std::string& error) {
317 base::ResetAndReturn(&done_callback_).Run(HandleJsonParseFailure(error));
318 // NOTE: |this| is not valid after the |done_callback_| is invoked.
319 }
320
321 class GetSTHLogResponseHandler : public LogResponseHandler {
322 public:
323 GetSTHLogResponseHandler(
324 const std::string& log_id,
325 const LogProofFetcher::SignedTreeHeadFetchedCallback& sth_fetch_callback,
326 const LogProofFetcher::FetchFailedCallback& failure_callback)
327 : LogResponseHandler(log_id, failure_callback),
328 sth_fetched_(sth_fetch_callback) {}
329
330 // Parses the JSON into a net::ct::SignedTreeHead and, if successful,
331 // invokes the success callback with it. Otherwise, invokes the failure
332 // callback indicating the error that occurred.
333 base::Closure HandleParsedJson(const base::Value& parsed_json) override {
334 net::ct::SignedTreeHead signed_tree_head;
335 if (!net::ct::FillSignedTreeHead(parsed_json, &signed_tree_head)) {
336 return base::Bind(base::ResetAndReturn(&failure_callback_), log_id_,
337 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK);
338 }
339
340 return base::Bind(base::ResetAndReturn(&sth_fetched_), log_id_,
341 signed_tree_head);
342 }
343
344 // Invoke the error callback indicating that STH parsing failed.
345 base::Closure HandleJsonParseFailure(const std::string& json_error) override {
346 return base::Bind(base::ResetAndReturn(&failure_callback_), log_id_,
347 net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK);
348 }
349
350 private:
351 LogProofFetcher::SignedTreeHeadFetchedCallback sth_fetched_;
352 };
353
354 class GetConsistencyProofLogResponseHandler : public LogResponseHandler {
355 public:
356 GetConsistencyProofLogResponseHandler(
357 const std::string& log_id,
358 const LogProofFetcher::ConsistencyProofFetchedCallback&
359 proof_fetch_callback,
360 const LogProofFetcher::FetchFailedCallback& failure_callback)
361 : LogResponseHandler(log_id, failure_callback),
362 proof_fetched_(proof_fetch_callback) {}
363
364 // Fills a vector of strings with nodes from the received consistency proof
365 // in |parsed_json|, and, if successful, invokes the success callback with the
366 // vector. Otherwise, invokes the failure callback indicating proof parsing
367 // has failed.
368 base::Closure HandleParsedJson(const base::Value& parsed_json) override {
369 std::vector<std::string> consistency_proof;
370 if (!net::ct::FillConsistencyProof(parsed_json, &consistency_proof)) {
371 return base::Bind(base::ResetAndReturn(&failure_callback_), log_id_,
372 net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED,
373 net::HTTP_OK);
374 }
375
376 return base::Bind(base::ResetAndReturn(&proof_fetched_), log_id_,
377 consistency_proof);
378 }
379
380 // Invoke the error callback indicating proof fetching failed.
381 base::Closure HandleJsonParseFailure(const std::string& json_error) override {
382 return base::Bind(base::ResetAndReturn(&failure_callback_), log_id_,
383 net::ERR_CT_CONSISTENCY_PROOF_PARSING_FAILED,
384 net::HTTP_OK);
385 }
386
387 private:
388 LogProofFetcher::ConsistencyProofFetchedCallback proof_fetched_;
389 };
68 390
69 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context) 391 LogProofFetcher::LogProofFetcher(net::URLRequestContext* request_context)
70 : request_context_(request_context), weak_factory_(this) { 392 : request_context_(request_context), weak_factory_(this) {
71 DCHECK(request_context); 393 DCHECK(request_context);
72 } 394 }
73 395
74 LogProofFetcher::~LogProofFetcher() { 396 LogProofFetcher::~LogProofFetcher() {
75 STLDeleteContainerPairPointers(inflight_requests_.begin(), 397 STLDeleteContainerPointers(inflight_fetches_.begin(),
76 inflight_requests_.end()); 398 inflight_fetches_.end());
77 } 399 }
78 400
79 void LogProofFetcher::FetchSignedTreeHead( 401 void LogProofFetcher::FetchSignedTreeHead(
80 const GURL& base_log_url, 402 const GURL& base_log_url,
81 const std::string& log_id, 403 const std::string& log_id,
82 const SignedTreeHeadFetchedCallback& fetched_callback, 404 const SignedTreeHeadFetchedCallback& fetched_callback,
83 const FetchFailedCallback& failed_callback) { 405 const FetchFailedCallback& failed_callback) {
84 DCHECK(base_log_url.SchemeIsHTTPOrHTTPS()); 406 GURL request_url = base_log_url.Resolve("ct/v1/get-sth");
85 GURL fetch_url(base_log_url.Resolve("ct/v1/get-sth")); 407 StartFetch(request_url, new GetSTHLogResponseHandler(log_id, fetched_callback,
86 scoped_ptr<net::URLRequest> request = 408 failed_callback));
87 request_context_->CreateRequest(fetch_url, net::DEFAULT_PRIORITY, this); 409 }
88 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 410
89 net::LOAD_DO_NOT_SAVE_COOKIES | 411 void LogProofFetcher::FetchConsistencyProof(
90 net::LOAD_DO_NOT_SEND_AUTH_DATA); 412 const GURL& base_log_url,
91 413 const std::string& log_id,
92 FetchState* fetch_state = 414 uint64_t old_tree_size,
93 new FetchState(log_id, fetched_callback, failed_callback); 415 uint64_t new_tree_size,
94 request->Start(); 416 const ConsistencyProofFetchedCallback& fetched_callback,
95 inflight_requests_.insert(std::make_pair(request.release(), fetch_state)); 417 const FetchFailedCallback& failed_callback) {
96 } 418 GURL request_url = base_log_url.Resolve(base::StringPrintf(
97 419 "ct/v1/get-sth-consistency?first=%" PRIu64 "&second=%" PRIu64,
98 void LogProofFetcher::OnResponseStarted(net::URLRequest* request) { 420 old_tree_size, new_tree_size));
99 net::URLRequestStatus status(request->status()); 421 StartFetch(request_url, new GetConsistencyProofLogResponseHandler(
100 DCHECK(inflight_requests_.count(request)); 422 log_id, fetched_callback, failed_callback));
101 FetchState* fetch_state = inflight_requests_.find(request)->second; 423 }
102 424
103 if (!status.is_success() || request->GetResponseCode() != net::HTTP_OK) { 425 void LogProofFetcher::StartFetch(const GURL& request_url,
104 int net_error = net::OK; 426 LogResponseHandler* log_request) {
105 int http_response_code = request->GetResponseCode(); 427 log_request->StartFetch(request_context_, request_url,
106 428 base::Bind(&LogProofFetcher::OnFetchDone,
107 DVLOG(1) << "Fetching STH from " << request->original_url() 429 weak_factory_.GetWeakPtr(), log_request));
108 << " failed. status:" << status.status() 430 inflight_fetches_.insert(log_request);
109 << " error:" << status.error() 431 }
110 << " http response code: " << http_response_code; 432
111 if (!status.is_success()) 433 void LogProofFetcher::OnFetchDone(LogResponseHandler* log_handler,
112 net_error = GetNetErrorFromURLRequestStatus(status); 434 const base::Closure& requestor_callback) {
113 435 auto it = inflight_fetches_.find(log_handler);
114 InvokeFailureCallback(request, net_error, http_response_code); 436 DCHECK(it != inflight_fetches_.end());
115 return; 437
116 } 438 delete *it;
117 439 inflight_fetches_.erase(it);
118 StartNextRead(request, fetch_state); 440 requestor_callback.Run();
119 }
120
121 void LogProofFetcher::OnReadCompleted(net::URLRequest* request,
122 int bytes_read) {
123 DCHECK(inflight_requests_.count(request));
124 FetchState* fetch_state = inflight_requests_.find(request)->second;
125
126 if (HandleReadResult(request, fetch_state, bytes_read))
127 StartNextRead(request, fetch_state);
128 }
129
130 bool LogProofFetcher::HandleReadResult(net::URLRequest* request,
131 FetchState* fetch_state,
132 int bytes_read) {
133 // Start by checking for an error condition.
134 // If there are errors, invoke the failure callback and clean up the
135 // request.
136 if (bytes_read == -1 || !request->status().is_success()) {
137 net::URLRequestStatus status(request->status());
138 DVLOG(1) << "Read error: " << status.status() << " " << status.error();
139 InvokeFailureCallback(request, GetNetErrorFromURLRequestStatus(status),
140 net::OK);
141
142 return false;
143 }
144
145 // Not an error, but no data available, so wait for OnReadCompleted
146 // callback.
147 if (request->status().is_io_pending())
148 return false;
149
150 // Nothing more to read from the stream - finish handling the response.
151 if (bytes_read == 0) {
152 RequestComplete(request);
153 return false;
154 }
155
156 // We have data, collect it and indicate another read is needed.
157 DVLOG(1) << "Have " << bytes_read << " bytes to assemble.";
158 DCHECK_GE(bytes_read, 0);
159 fetch_state->assembled_response.append(fetch_state->response_buffer->data(),
160 bytes_read);
161 if (fetch_state->assembled_response.size() > kMaxLogResponseSizeInBytes) {
162 // Log response is too big, invoke the failure callback.
163 InvokeFailureCallback(request, net::ERR_FILE_TOO_BIG, net::HTTP_OK);
164 return false;
165 }
166
167 return true;
168 }
169
170 void LogProofFetcher::StartNextRead(net::URLRequest* request,
171 FetchState* fetch_state) {
172 bool continue_reading = true;
173 while (continue_reading) {
174 int read_bytes = 0;
175 request->Read(fetch_state->response_buffer.get(),
176 fetch_state->response_buffer->size(), &read_bytes);
177 continue_reading = HandleReadResult(request, fetch_state, read_bytes);
178 }
179 }
180
181 void LogProofFetcher::RequestComplete(net::URLRequest* request) {
182 DCHECK(inflight_requests_.count(request));
183
184 FetchState* fetch_state = inflight_requests_.find(request)->second;
185
186 // Get rid of the buffer as it really isn't necessary.
187 fetch_state->response_buffer = nullptr;
188 safe_json::SafeJsonParser::Parse(
189 fetch_state->assembled_response,
190 base::Bind(&LogProofFetcher::OnSTHJsonParseSuccess,
191 weak_factory_.GetWeakPtr(), request),
192 base::Bind(&LogProofFetcher::OnSTHJsonParseError,
193 weak_factory_.GetWeakPtr(), request));
194 }
195
196 void LogProofFetcher::CleanupRequest(net::URLRequest* request) {
197 DVLOG(1) << "Cleaning up request to " << request->original_url();
198 auto it = inflight_requests_.find(request);
199 DCHECK(it != inflight_requests_.end());
200 auto next_it = it;
201 std::advance(next_it, 1);
202
203 // Delete FetchState and URLRequest, then the entry from inflight_requests_.
204 STLDeleteContainerPairPointers(it, next_it);
205 inflight_requests_.erase(it);
206 }
207
208 void LogProofFetcher::InvokeFailureCallback(net::URLRequest* request,
209 int net_error,
210 int http_response_code) {
211 DCHECK(inflight_requests_.count(request));
212 auto it = inflight_requests_.find(request);
213 FetchState* fetch_state = it->second;
214
215 fetch_state->failed_callback.Run(fetch_state->log_id, net_error,
216 http_response_code);
217 CleanupRequest(request);
218 }
219
220 void LogProofFetcher::OnSTHJsonParseSuccess(
221 net::URLRequest* request,
222 scoped_ptr<base::Value> parsed_json) {
223 DCHECK(inflight_requests_.count(request));
224
225 FetchState* fetch_state = inflight_requests_.find(request)->second;
226 net::ct::SignedTreeHead signed_tree_head;
227 if (net::ct::FillSignedTreeHead(*parsed_json.get(), &signed_tree_head)) {
228 fetch_state->fetched_callback.Run(fetch_state->log_id, signed_tree_head);
229 } else {
230 fetch_state->failed_callback.Run(fetch_state->log_id,
231 net::ERR_CT_STH_INCOMPLETE, net::HTTP_OK);
232 }
233
234 CleanupRequest(request);
235 }
236
237 void LogProofFetcher::OnSTHJsonParseError(net::URLRequest* request,
238 const std::string& error) {
239 InvokeFailureCallback(request, net::ERR_CT_STH_PARSING_FAILED, net::HTTP_OK);
240 } 441 }
241 442
242 } // namespace certificate_transparency 443 } // namespace certificate_transparency
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698