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 |