| OLD | NEW |
| 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 #include <memory> | 8 #include <memory> |
| 9 | 9 |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 public: | 40 public: |
| 41 using FailureCallback = base::Callback<void(int, int)>; | 41 using FailureCallback = base::Callback<void(int, int)>; |
| 42 | 42 |
| 43 LogFetcher(net::URLRequestContext* request_context, | 43 LogFetcher(net::URLRequestContext* request_context, |
| 44 const GURL& request_url, | 44 const GURL& request_url, |
| 45 const base::Closure& success_callback, | 45 const base::Closure& success_callback, |
| 46 const FailureCallback& failure_callback); | 46 const FailureCallback& failure_callback); |
| 47 ~LogFetcher() override {} | 47 ~LogFetcher() override {} |
| 48 | 48 |
| 49 // net::URLRequest::Delegate | 49 // net::URLRequest::Delegate |
| 50 void OnResponseStarted(net::URLRequest* request) override; | 50 void OnResponseStarted(net::URLRequest* request, int net_error) override; |
| 51 void OnReadCompleted(net::URLRequest* request, int bytes_read) override; | 51 void OnReadCompleted(net::URLRequest* request, int bytes_read) override; |
| 52 | 52 |
| 53 const std::string& assembled_response() const { return assembled_response_; } | 53 const std::string& assembled_response() const { return assembled_response_; } |
| 54 | 54 |
| 55 private: | 55 private: |
| 56 // Handles the final result of a URLRequest::Read call on the request. | 56 // Handles the final result of a URLRequest::Read call on the request. |
| 57 // Returns true if another read should be started, false if the read | 57 // Returns true if another read should be started, false if the read |
| 58 // failed completely or we have to wait for OnResponseStarted to | 58 // failed completely or we have to wait for OnResponseStarted to |
| 59 // be called. | 59 // be called. |
| 60 bool HandleReadResult(int bytes_read); | 60 bool HandleReadResult(int result); |
| 61 | 61 |
| 62 // Calls URLRequest::Read on |request| repeatedly, until HandleReadResult | 62 // Calls URLRequest::Read on |request| repeatedly, until HandleReadResult |
| 63 // indicates it should no longer be called. Usually this would be when there | 63 // indicates it should no longer be called. Usually this would be when there |
| 64 // is pending IO that requires waiting for OnResponseStarted to be called. | 64 // is pending IO that requires waiting for OnResponseStarted to be called. |
| 65 void StartNextReadLoop(); | 65 void StartNextReadLoop(); |
| 66 | 66 |
| 67 // Invokes the success callback. After this method is called, the LogFetcher | 67 // Invokes the success callback. After this method is called, the LogFetcher |
| 68 // is deleted and no longer safe to call. | 68 // is deleted and no longer safe to call. |
| 69 void RequestComplete(); | 69 void RequestComplete(); |
| 70 | 70 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 95 // This request should not send any cookies or otherwise identifying data, | 95 // This request should not send any cookies or otherwise identifying data, |
| 96 // as CT logs are expected to be publicly-accessible and connections to them | 96 // as CT logs are expected to be publicly-accessible and connections to them |
| 97 // stateless. | 97 // stateless. |
| 98 url_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 98 url_request_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 99 net::LOAD_DO_NOT_SAVE_COOKIES | | 99 net::LOAD_DO_NOT_SAVE_COOKIES | |
| 100 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 100 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
| 101 | 101 |
| 102 url_request_->Start(); | 102 url_request_->Start(); |
| 103 } | 103 } |
| 104 | 104 |
| 105 void LogFetcher::OnResponseStarted(net::URLRequest* request) { | 105 void LogFetcher::OnResponseStarted(net::URLRequest* request, int net_error) { |
| 106 DCHECK_NE(net::ERR_IO_PENDING, net_error); |
| 106 DCHECK_EQ(url_request_.get(), request); | 107 DCHECK_EQ(url_request_.get(), request); |
| 107 int http_response_code = request->GetResponseCode(); | 108 int http_response_code = request->GetResponseCode(); |
| 108 | 109 |
| 109 if (!request->status().is_success()) { | 110 if (net_error != net::OK) { |
| 110 InvokeFailureCallback(request->status().error(), http_response_code); | 111 InvokeFailureCallback(net_error, http_response_code); |
| 111 return; | 112 return; |
| 112 } | 113 } |
| 113 | 114 |
| 114 if (http_response_code != net::HTTP_OK) { | 115 if (http_response_code != net::HTTP_OK) { |
| 115 InvokeFailureCallback(net::OK, http_response_code); | 116 InvokeFailureCallback(net::OK, http_response_code); |
| 116 return; | 117 return; |
| 117 } | 118 } |
| 118 | 119 |
| 119 // Lazily initialize |response_buffer_| to avoid consuming memory until an | 120 // Lazily initialize |response_buffer_| to avoid consuming memory until an |
| 120 // actual response has been received. | 121 // actual response has been received. |
| 121 if (!response_buffer_) { | 122 if (!response_buffer_) { |
| 122 response_buffer_ = | 123 response_buffer_ = |
| 123 new net::IOBufferWithSize(LogProofFetcher::kMaxLogResponseSizeInBytes); | 124 new net::IOBufferWithSize(LogProofFetcher::kMaxLogResponseSizeInBytes); |
| 124 } | 125 } |
| 125 | 126 |
| 126 StartNextReadLoop(); | 127 StartNextReadLoop(); |
| 127 } | 128 } |
| 128 | 129 |
| 129 void LogFetcher::OnReadCompleted(net::URLRequest* request, int bytes_read) { | 130 void LogFetcher::OnReadCompleted(net::URLRequest* request, int bytes_read) { |
| 130 DCHECK_EQ(url_request_.get(), request); | 131 DCHECK_EQ(url_request_.get(), request); |
| 131 | 132 |
| 132 if (HandleReadResult(bytes_read)) | 133 if (HandleReadResult(bytes_read)) |
| 133 StartNextReadLoop(); | 134 StartNextReadLoop(); |
| 134 } | 135 } |
| 135 | 136 |
| 136 bool LogFetcher::HandleReadResult(int bytes_read) { | 137 bool LogFetcher::HandleReadResult(int result) { |
| 137 // Start by checking for an error condition. | 138 if (result == net::ERR_IO_PENDING) |
| 138 // If there are errors, invoke the failure callback and clean up the | 139 return false; |
| 139 // request. | |
| 140 if (!url_request_->status().is_success() || bytes_read < 0) { | |
| 141 int net_error = url_request_->status().error(); | |
| 142 if (net_error == net::OK) | |
| 143 net_error = net::URLRequestStatus::FAILED; | |
| 144 | 140 |
| 145 InvokeFailureCallback(net_error, net::HTTP_OK); | 141 if (result < 0) { |
| 142 InvokeFailureCallback(result, net::HTTP_OK); |
| 146 return false; | 143 return false; |
| 147 } | 144 } |
| 148 | 145 |
| 149 // Not an error, but no data available, so wait for OnReadCompleted | |
| 150 // callback. | |
| 151 if (url_request_->status().is_io_pending()) | |
| 152 return false; | |
| 153 | |
| 154 // Nothing more to read from the stream - finish handling the response. | 146 // Nothing more to read from the stream - finish handling the response. |
| 155 if (bytes_read == 0) { | 147 if (result == 0) { |
| 156 RequestComplete(); | 148 RequestComplete(); |
| 157 return false; | 149 return false; |
| 158 } | 150 } |
| 159 | 151 |
| 160 // Data is available, collect it and indicate another read is needed. | 152 // Data is available, collect it and indicate another read is needed. |
| 161 DCHECK_GE(bytes_read, 0); | 153 DCHECK_GE(result, 0); |
| 162 // |bytes_read| is non-negative at this point, casting to size_t should be | 154 // |result| is non-negative at this point, casting to size_t should be |
| 163 // safe. | 155 // safe. |
| 164 if (base::checked_cast<size_t>(bytes_read) > | 156 if (base::checked_cast<size_t>(result) > |
| 165 LogProofFetcher::kMaxLogResponseSizeInBytes || | 157 LogProofFetcher::kMaxLogResponseSizeInBytes || |
| 166 LogProofFetcher::kMaxLogResponseSizeInBytes < | 158 LogProofFetcher::kMaxLogResponseSizeInBytes < |
| 167 (assembled_response_.size() + bytes_read)) { | 159 (assembled_response_.size() + result)) { |
| 168 // Log response is too big, invoke the failure callback. | 160 // Log response is too big, invoke the failure callback. |
| 169 InvokeFailureCallback(net::ERR_FILE_TOO_BIG, net::HTTP_OK); | 161 InvokeFailureCallback(net::ERR_FILE_TOO_BIG, net::HTTP_OK); |
| 170 return false; | 162 return false; |
| 171 } | 163 } |
| 172 | 164 |
| 173 assembled_response_.append(response_buffer_->data(), bytes_read); | 165 assembled_response_.append(response_buffer_->data(), result); |
| 174 return true; | 166 return true; |
| 175 } | 167 } |
| 176 | 168 |
| 177 void LogFetcher::StartNextReadLoop() { | 169 void LogFetcher::StartNextReadLoop() { |
| 178 bool continue_reading = true; | 170 bool continue_reading = true; |
| 179 while (continue_reading) { | 171 while (continue_reading) { |
| 180 int read_bytes = 0; | 172 int read_bytes = |
| 181 url_request_->Read(response_buffer_.get(), response_buffer_->size(), | 173 url_request_->Read(response_buffer_.get(), response_buffer_->size()); |
| 182 &read_bytes); | |
| 183 continue_reading = HandleReadResult(read_bytes); | 174 continue_reading = HandleReadResult(read_bytes); |
| 184 } | 175 } |
| 185 } | 176 } |
| 186 | 177 |
| 187 void LogFetcher::RequestComplete() { | 178 void LogFetcher::RequestComplete() { |
| 188 // Get rid of the buffer as it really isn't necessary. | 179 // Get rid of the buffer as it really isn't necessary. |
| 189 response_buffer_ = nullptr; | 180 response_buffer_ = nullptr; |
| 190 base::ResetAndReturn(&success_callback_).Run(); | 181 base::ResetAndReturn(&success_callback_).Run(); |
| 191 // NOTE: |this| is not valid after invoking the callback, as the LogFetcher | 182 // NOTE: |this| is not valid after invoking the callback, as the LogFetcher |
| 192 // instance will be deleted by the callback. | 183 // instance will be deleted by the callback. |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 const base::Closure& requestor_callback) { | 428 const base::Closure& requestor_callback) { |
| 438 auto it = inflight_fetches_.find(log_handler); | 429 auto it = inflight_fetches_.find(log_handler); |
| 439 DCHECK(it != inflight_fetches_.end()); | 430 DCHECK(it != inflight_fetches_.end()); |
| 440 | 431 |
| 441 delete *it; | 432 delete *it; |
| 442 inflight_fetches_.erase(it); | 433 inflight_fetches_.erase(it); |
| 443 requestor_callback.Run(); | 434 requestor_callback.Run(); |
| 444 } | 435 } |
| 445 | 436 |
| 446 } // namespace certificate_transparency | 437 } // namespace certificate_transparency |
| OLD | NEW |