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 bytes_read); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after 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 bytes_read) { |
137 // Start by checking for an error condition. | |
138 // If there are errors, invoke the failure callback and clean up the | |
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 | |
145 InvokeFailureCallback(net_error, net::HTTP_OK); | |
146 return false; | |
147 } | |
148 | |
149 // Not an error, but no data available, so wait for OnReadCompleted | 138 // Not an error, but no data available, so wait for OnReadCompleted |
150 // callback. | 139 // callback. |
151 if (url_request_->status().is_io_pending()) | 140 if (bytes_read == net::ERR_IO_PENDING) |
152 return false; | 141 return false; |
153 | 142 |
154 // Nothing more to read from the stream - finish handling the response. | 143 // Nothing more to read from the stream - finish handling the response. |
155 if (bytes_read == 0) { | 144 if (bytes_read == 0) { |
156 RequestComplete(); | 145 RequestComplete(); |
157 return false; | 146 return false; |
158 } | 147 } |
159 | 148 |
149 // Check for an error condition. | |
Ryan Sleevi
2016/09/07 18:48:08
You can drop this line; it no longer grammatically
| |
150 // If there are errors, invoke the failure callback and clean up the | |
151 // request. | |
152 if (bytes_read < 0) { | |
153 int net_error = bytes_read; | |
154 InvokeFailureCallback(net_error, net::HTTP_OK); | |
155 return false; | |
156 } | |
157 | |
160 // Data is available, collect it and indicate another read is needed. | 158 // Data is available, collect it and indicate another read is needed. |
161 DCHECK_GE(bytes_read, 0); | 159 DCHECK_GE(bytes_read, 0); |
162 // |bytes_read| is non-negative at this point, casting to size_t should be | 160 // |bytes_read| is non-negative at this point, casting to size_t should be |
163 // safe. | 161 // safe. |
164 if (base::checked_cast<size_t>(bytes_read) > | 162 if (base::checked_cast<size_t>(bytes_read) > |
165 LogProofFetcher::kMaxLogResponseSizeInBytes || | 163 LogProofFetcher::kMaxLogResponseSizeInBytes || |
166 LogProofFetcher::kMaxLogResponseSizeInBytes < | 164 LogProofFetcher::kMaxLogResponseSizeInBytes < |
167 (assembled_response_.size() + bytes_read)) { | 165 (assembled_response_.size() + bytes_read)) { |
168 // Log response is too big, invoke the failure callback. | 166 // Log response is too big, invoke the failure callback. |
169 InvokeFailureCallback(net::ERR_FILE_TOO_BIG, net::HTTP_OK); | 167 InvokeFailureCallback(net::ERR_FILE_TOO_BIG, net::HTTP_OK); |
170 return false; | 168 return false; |
171 } | 169 } |
172 | 170 |
173 assembled_response_.append(response_buffer_->data(), bytes_read); | 171 assembled_response_.append(response_buffer_->data(), bytes_read); |
174 return true; | 172 return true; |
175 } | 173 } |
176 | 174 |
177 void LogFetcher::StartNextReadLoop() { | 175 void LogFetcher::StartNextReadLoop() { |
178 bool continue_reading = true; | 176 bool continue_reading = true; |
179 while (continue_reading) { | 177 while (continue_reading) { |
180 int read_bytes = 0; | 178 int read_bytes = |
181 url_request_->Read(response_buffer_.get(), response_buffer_->size(), | 179 url_request_->Read(response_buffer_.get(), response_buffer_->size()); |
182 &read_bytes); | |
183 continue_reading = HandleReadResult(read_bytes); | 180 continue_reading = HandleReadResult(read_bytes); |
184 } | 181 } |
185 } | 182 } |
186 | 183 |
187 void LogFetcher::RequestComplete() { | 184 void LogFetcher::RequestComplete() { |
188 // Get rid of the buffer as it really isn't necessary. | 185 // Get rid of the buffer as it really isn't necessary. |
189 response_buffer_ = nullptr; | 186 response_buffer_ = nullptr; |
190 base::ResetAndReturn(&success_callback_).Run(); | 187 base::ResetAndReturn(&success_callback_).Run(); |
191 // NOTE: |this| is not valid after invoking the callback, as the LogFetcher | 188 // NOTE: |this| is not valid after invoking the callback, as the LogFetcher |
192 // instance will be deleted by the callback. | 189 // 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) { | 434 const base::Closure& requestor_callback) { |
438 auto it = inflight_fetches_.find(log_handler); | 435 auto it = inflight_fetches_.find(log_handler); |
439 DCHECK(it != inflight_fetches_.end()); | 436 DCHECK(it != inflight_fetches_.end()); |
440 | 437 |
441 delete *it; | 438 delete *it; |
442 inflight_fetches_.erase(it); | 439 inflight_fetches_.erase(it); |
443 requestor_callback.Run(); | 440 requestor_callback.Run(); |
444 } | 441 } |
445 | 442 |
446 } // namespace certificate_transparency | 443 } // namespace certificate_transparency |
OLD | NEW |