OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/http/http_stream_parser.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/compiler_specific.h" | |
9 #include "base/logging.h" | |
10 #include "base/profiler/scoped_tracker.h" | |
11 #include "base/strings/string_util.h" | |
12 #include "base/values.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "net/base/ip_endpoint.h" | |
15 #include "net/base/upload_data_stream.h" | |
16 #include "net/http/http_chunked_decoder.h" | |
17 #include "net/http/http_request_headers.h" | |
18 #include "net/http/http_request_info.h" | |
19 #include "net/http/http_response_headers.h" | |
20 #include "net/http/http_util.h" | |
21 #include "net/socket/client_socket_handle.h" | |
22 #include "net/socket/ssl_client_socket.h" | |
23 | |
24 namespace net { | |
25 | |
26 namespace { | |
27 | |
28 const uint64 kMaxMergedHeaderAndBodySize = 1400; | |
29 const size_t kRequestBodyBufferSize = 1 << 14; // 16KB | |
30 | |
31 std::string GetResponseHeaderLines(const HttpResponseHeaders& headers) { | |
32 std::string raw_headers = headers.raw_headers(); | |
33 const char* null_separated_headers = raw_headers.c_str(); | |
34 const char* header_line = null_separated_headers; | |
35 std::string cr_separated_headers; | |
36 while (header_line[0] != 0) { | |
37 cr_separated_headers += header_line; | |
38 cr_separated_headers += "\n"; | |
39 header_line += strlen(header_line) + 1; | |
40 } | |
41 return cr_separated_headers; | |
42 } | |
43 | |
44 // Return true if |headers| contain multiple |field_name| fields with different | |
45 // values. | |
46 bool HeadersContainMultipleCopiesOfField(const HttpResponseHeaders& headers, | |
47 const std::string& field_name) { | |
48 void* it = NULL; | |
49 std::string field_value; | |
50 if (!headers.EnumerateHeader(&it, field_name, &field_value)) | |
51 return false; | |
52 // There's at least one |field_name| header. Check if there are any more | |
53 // such headers, and if so, return true if they have different values. | |
54 std::string field_value2; | |
55 while (headers.EnumerateHeader(&it, field_name, &field_value2)) { | |
56 if (field_value != field_value2) | |
57 return true; | |
58 } | |
59 return false; | |
60 } | |
61 | |
62 base::Value* NetLogSendRequestBodyCallback(uint64 length, | |
63 bool is_chunked, | |
64 bool did_merge, | |
65 NetLog::LogLevel /* log_level */) { | |
66 base::DictionaryValue* dict = new base::DictionaryValue(); | |
67 dict->SetInteger("length", static_cast<int>(length)); | |
68 dict->SetBoolean("is_chunked", is_chunked); | |
69 dict->SetBoolean("did_merge", did_merge); | |
70 return dict; | |
71 } | |
72 | |
73 // Returns true if |error_code| is an error for which we give the server a | |
74 // chance to send a body containing error information, if the error was received | |
75 // while trying to upload a request body. | |
76 bool ShouldTryReadingOnUploadError(int error_code) { | |
77 return (error_code == ERR_CONNECTION_RESET); | |
78 } | |
79 | |
80 } // namespace | |
81 | |
82 // Similar to DrainableIOBuffer(), but this version comes with its own | |
83 // storage. The motivation is to avoid repeated allocations of | |
84 // DrainableIOBuffer. | |
85 // | |
86 // Example: | |
87 // | |
88 // scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024); | |
89 // // capacity() == 1024. size() == BytesRemaining() == BytesConsumed() == 0. | |
90 // // data() points to the beginning of the buffer. | |
91 // | |
92 // // Read() takes an IOBuffer. | |
93 // int bytes_read = some_reader->Read(buf, buf->capacity()); | |
94 // buf->DidAppend(bytes_read); | |
95 // // size() == BytesRemaining() == bytes_read. data() is unaffected. | |
96 // | |
97 // while (buf->BytesRemaining() > 0) { | |
98 // // Write() takes an IOBuffer. If it takes const char*, we could | |
99 /// // simply use the regular IOBuffer like buf->data() + offset. | |
100 // int bytes_written = Write(buf, buf->BytesRemaining()); | |
101 // buf->DidConsume(bytes_written); | |
102 // } | |
103 // // BytesRemaining() == 0. BytesConsumed() == size(). | |
104 // // data() points to the end of the consumed bytes (exclusive). | |
105 // | |
106 // // If you want to reuse the buffer, be sure to clear the buffer. | |
107 // buf->Clear(); | |
108 // // size() == BytesRemaining() == BytesConsumed() == 0. | |
109 // // data() points to the beginning of the buffer. | |
110 // | |
111 class HttpStreamParser::SeekableIOBuffer : public IOBuffer { | |
112 public: | |
113 explicit SeekableIOBuffer(int capacity) | |
114 : IOBuffer(capacity), | |
115 real_data_(data_), | |
116 capacity_(capacity), | |
117 size_(0), | |
118 used_(0) { | |
119 } | |
120 | |
121 // DidConsume() changes the |data_| pointer so that |data_| always points | |
122 // to the first unconsumed byte. | |
123 void DidConsume(int bytes) { | |
124 SetOffset(used_ + bytes); | |
125 } | |
126 | |
127 // Returns the number of unconsumed bytes. | |
128 int BytesRemaining() const { | |
129 return size_ - used_; | |
130 } | |
131 | |
132 // Seeks to an arbitrary point in the buffer. The notion of bytes consumed | |
133 // and remaining are updated appropriately. | |
134 void SetOffset(int bytes) { | |
135 DCHECK_GE(bytes, 0); | |
136 DCHECK_LE(bytes, size_); | |
137 used_ = bytes; | |
138 data_ = real_data_ + used_; | |
139 } | |
140 | |
141 // Called after data is added to the buffer. Adds |bytes| added to | |
142 // |size_|. data() is unaffected. | |
143 void DidAppend(int bytes) { | |
144 DCHECK_GE(bytes, 0); | |
145 DCHECK_GE(size_ + bytes, 0); | |
146 DCHECK_LE(size_ + bytes, capacity_); | |
147 size_ += bytes; | |
148 } | |
149 | |
150 // Changes the logical size to 0, and the offset to 0. | |
151 void Clear() { | |
152 size_ = 0; | |
153 SetOffset(0); | |
154 } | |
155 | |
156 // Returns the logical size of the buffer (i.e the number of bytes of data | |
157 // in the buffer). | |
158 int size() const { return size_; } | |
159 | |
160 // Returns the capacity of the buffer. The capacity is the size used when | |
161 // the object is created. | |
162 int capacity() const { return capacity_; }; | |
163 | |
164 private: | |
165 ~SeekableIOBuffer() override { | |
166 // data_ will be deleted in IOBuffer::~IOBuffer(). | |
167 data_ = real_data_; | |
168 } | |
169 | |
170 char* real_data_; | |
171 const int capacity_; | |
172 int size_; | |
173 int used_; | |
174 }; | |
175 | |
176 // 2 CRLFs + max of 8 hex chars. | |
177 const size_t HttpStreamParser::kChunkHeaderFooterSize = 12; | |
178 | |
179 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, | |
180 const HttpRequestInfo* request, | |
181 GrowableIOBuffer* read_buffer, | |
182 const BoundNetLog& net_log) | |
183 : io_state_(STATE_NONE), | |
184 request_(request), | |
185 request_headers_(NULL), | |
186 request_headers_length_(0), | |
187 read_buf_(read_buffer), | |
188 read_buf_unused_offset_(0), | |
189 response_header_start_offset_(-1), | |
190 received_bytes_(0), | |
191 response_body_length_(-1), | |
192 response_body_read_(0), | |
193 user_read_buf_(NULL), | |
194 user_read_buf_len_(0), | |
195 connection_(connection), | |
196 net_log_(net_log), | |
197 sent_last_chunk_(false), | |
198 upload_error_(OK), | |
199 weak_ptr_factory_(this) { | |
200 io_callback_ = base::Bind(&HttpStreamParser::OnIOComplete, | |
201 weak_ptr_factory_.GetWeakPtr()); | |
202 } | |
203 | |
204 HttpStreamParser::~HttpStreamParser() { | |
205 } | |
206 | |
207 int HttpStreamParser::SendRequest(const std::string& request_line, | |
208 const HttpRequestHeaders& headers, | |
209 HttpResponseInfo* response, | |
210 const CompletionCallback& callback) { | |
211 DCHECK_EQ(STATE_NONE, io_state_); | |
212 DCHECK(callback_.is_null()); | |
213 DCHECK(!callback.is_null()); | |
214 DCHECK(response); | |
215 | |
216 net_log_.AddEvent( | |
217 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, | |
218 base::Bind(&HttpRequestHeaders::NetLogCallback, | |
219 base::Unretained(&headers), | |
220 &request_line)); | |
221 | |
222 DVLOG(1) << __FUNCTION__ << "()" | |
223 << " request_line = \"" << request_line << "\"" | |
224 << " headers = \"" << headers.ToString() << "\""; | |
225 response_ = response; | |
226 | |
227 // Put the peer's IP address and port into the response. | |
228 IPEndPoint ip_endpoint; | |
229 int result = connection_->socket()->GetPeerAddress(&ip_endpoint); | |
230 if (result != OK) | |
231 return result; | |
232 response_->socket_address = HostPortPair::FromIPEndPoint(ip_endpoint); | |
233 | |
234 std::string request = request_line + headers.ToString(); | |
235 request_headers_length_ = request.size(); | |
236 | |
237 if (request_->upload_data_stream != NULL) { | |
238 request_body_send_buf_ = new SeekableIOBuffer(kRequestBodyBufferSize); | |
239 if (request_->upload_data_stream->is_chunked()) { | |
240 // Read buffer is adjusted to guarantee that |request_body_send_buf_| is | |
241 // large enough to hold the encoded chunk. | |
242 request_body_read_buf_ = | |
243 new SeekableIOBuffer(kRequestBodyBufferSize - kChunkHeaderFooterSize); | |
244 } else { | |
245 // No need to encode request body, just send the raw data. | |
246 request_body_read_buf_ = request_body_send_buf_; | |
247 } | |
248 } | |
249 | |
250 io_state_ = STATE_SEND_HEADERS; | |
251 | |
252 // If we have a small request body, then we'll merge with the headers into a | |
253 // single write. | |
254 bool did_merge = false; | |
255 if (ShouldMergeRequestHeadersAndBody(request, request_->upload_data_stream)) { | |
256 int merged_size = static_cast<int>( | |
257 request_headers_length_ + request_->upload_data_stream->size()); | |
258 scoped_refptr<IOBuffer> merged_request_headers_and_body( | |
259 new IOBuffer(merged_size)); | |
260 // We'll repurpose |request_headers_| to store the merged headers and | |
261 // body. | |
262 request_headers_ = new DrainableIOBuffer( | |
263 merged_request_headers_and_body.get(), merged_size); | |
264 | |
265 memcpy(request_headers_->data(), request.data(), request_headers_length_); | |
266 request_headers_->DidConsume(request_headers_length_); | |
267 | |
268 uint64 todo = request_->upload_data_stream->size(); | |
269 while (todo) { | |
270 int consumed = request_->upload_data_stream->Read( | |
271 request_headers_.get(), static_cast<int>(todo), CompletionCallback()); | |
272 DCHECK_GT(consumed, 0); // Read() won't fail if not chunked. | |
273 request_headers_->DidConsume(consumed); | |
274 todo -= consumed; | |
275 } | |
276 DCHECK(request_->upload_data_stream->IsEOF()); | |
277 // Reset the offset, so the buffer can be read from the beginning. | |
278 request_headers_->SetOffset(0); | |
279 did_merge = true; | |
280 | |
281 net_log_.AddEvent( | |
282 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, | |
283 base::Bind(&NetLogSendRequestBodyCallback, | |
284 request_->upload_data_stream->size(), | |
285 false, /* not chunked */ | |
286 true /* merged */)); | |
287 } | |
288 | |
289 if (!did_merge) { | |
290 // If we didn't merge the body with the headers, then |request_headers_| | |
291 // contains just the HTTP headers. | |
292 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); | |
293 request_headers_ = | |
294 new DrainableIOBuffer(headers_io_buf.get(), headers_io_buf->size()); | |
295 } | |
296 | |
297 result = DoLoop(OK); | |
298 if (result == ERR_IO_PENDING) | |
299 callback_ = callback; | |
300 | |
301 return result > 0 ? OK : result; | |
302 } | |
303 | |
304 int HttpStreamParser::ReadResponseHeaders(const CompletionCallback& callback) { | |
305 DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); | |
306 DCHECK(callback_.is_null()); | |
307 DCHECK(!callback.is_null()); | |
308 DCHECK_EQ(0, read_buf_unused_offset_); | |
309 | |
310 // This function can be called with io_state_ == STATE_DONE if the | |
311 // connection is closed after seeing just a 1xx response code. | |
312 if (io_state_ == STATE_DONE) | |
313 return ERR_CONNECTION_CLOSED; | |
314 | |
315 int result = OK; | |
316 io_state_ = STATE_READ_HEADERS; | |
317 | |
318 if (read_buf_->offset() > 0) { | |
319 // Simulate the state where the data was just read from the socket. | |
320 result = read_buf_->offset(); | |
321 read_buf_->set_offset(0); | |
322 } | |
323 if (result > 0) | |
324 io_state_ = STATE_READ_HEADERS_COMPLETE; | |
325 | |
326 result = DoLoop(result); | |
327 if (result == ERR_IO_PENDING) | |
328 callback_ = callback; | |
329 | |
330 return result > 0 ? OK : result; | |
331 } | |
332 | |
333 void HttpStreamParser::Close(bool not_reusable) { | |
334 if (not_reusable && connection_->socket()) | |
335 connection_->socket()->Disconnect(); | |
336 connection_->Reset(); | |
337 } | |
338 | |
339 int HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len, | |
340 const CompletionCallback& callback) { | |
341 DCHECK(io_state_ == STATE_NONE || io_state_ == STATE_DONE); | |
342 DCHECK(callback_.is_null()); | |
343 DCHECK(!callback.is_null()); | |
344 DCHECK_LE(buf_len, kMaxBufSize); | |
345 | |
346 if (io_state_ == STATE_DONE) | |
347 return OK; | |
348 | |
349 user_read_buf_ = buf; | |
350 user_read_buf_len_ = buf_len; | |
351 io_state_ = STATE_READ_BODY; | |
352 | |
353 int result = DoLoop(OK); | |
354 if (result == ERR_IO_PENDING) | |
355 callback_ = callback; | |
356 | |
357 return result; | |
358 } | |
359 | |
360 void HttpStreamParser::OnIOComplete(int result) { | |
361 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed. | |
362 tracked_objects::ScopedTracker tracking_profile( | |
363 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
364 "418183 DidCompleteReadWrite => HttpStreamParser::OnIOComplete")); | |
365 | |
366 result = DoLoop(result); | |
367 | |
368 // The client callback can do anything, including destroying this class, | |
369 // so any pending callback must be issued after everything else is done. | |
370 if (result != ERR_IO_PENDING && !callback_.is_null()) { | |
371 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed. | |
372 tracked_objects::ScopedTracker tracking_profile( | |
373 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
374 "424359 HttpStreamParser::OnIOComplete callback")); | |
375 | |
376 CompletionCallback c = callback_; | |
377 callback_.Reset(); | |
378 c.Run(result); | |
379 } | |
380 } | |
381 | |
382 int HttpStreamParser::DoLoop(int result) { | |
383 // TODO(vadimt): Remove ScopedTracker below once crbug.com/424359 is fixed. | |
384 tracked_objects::ScopedTracker tracking_profile( | |
385 FROM_HERE_WITH_EXPLICIT_FUNCTION("424359 HttpStreamParser::DoLoop")); | |
386 | |
387 do { | |
388 DCHECK_NE(ERR_IO_PENDING, result); | |
389 DCHECK_NE(STATE_DONE, io_state_); | |
390 DCHECK_NE(STATE_NONE, io_state_); | |
391 State state = io_state_; | |
392 io_state_ = STATE_NONE; | |
393 switch (state) { | |
394 case STATE_SEND_HEADERS: | |
395 DCHECK_EQ(OK, result); | |
396 result = DoSendHeaders(); | |
397 break; | |
398 case STATE_SEND_HEADERS_COMPLETE: | |
399 result = DoSendHeadersComplete(result); | |
400 break; | |
401 case STATE_SEND_BODY: | |
402 DCHECK_EQ(OK, result); | |
403 result = DoSendBody(); | |
404 break; | |
405 case STATE_SEND_BODY_COMPLETE: | |
406 result = DoSendBodyComplete(result); | |
407 break; | |
408 case STATE_SEND_REQUEST_READ_BODY_COMPLETE: | |
409 result = DoSendRequestReadBodyComplete(result); | |
410 break; | |
411 case STATE_READ_HEADERS: | |
412 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS); | |
413 DCHECK_GE(result, 0); | |
414 result = DoReadHeaders(); | |
415 break; | |
416 case STATE_READ_HEADERS_COMPLETE: | |
417 result = DoReadHeadersComplete(result); | |
418 net_log_.EndEventWithNetErrorCode( | |
419 NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result); | |
420 break; | |
421 case STATE_READ_BODY: | |
422 DCHECK_GE(result, 0); | |
423 result = DoReadBody(); | |
424 break; | |
425 case STATE_READ_BODY_COMPLETE: | |
426 result = DoReadBodyComplete(result); | |
427 break; | |
428 default: | |
429 NOTREACHED(); | |
430 break; | |
431 } | |
432 } while (result != ERR_IO_PENDING && | |
433 (io_state_ != STATE_DONE && io_state_ != STATE_NONE)); | |
434 | |
435 return result; | |
436 } | |
437 | |
438 int HttpStreamParser::DoSendHeaders() { | |
439 int bytes_remaining = request_headers_->BytesRemaining(); | |
440 DCHECK_GT(bytes_remaining, 0); | |
441 | |
442 // Record our best estimate of the 'request time' as the time when we send | |
443 // out the first bytes of the request headers. | |
444 if (bytes_remaining == request_headers_->size()) | |
445 response_->request_time = base::Time::Now(); | |
446 | |
447 io_state_ = STATE_SEND_HEADERS_COMPLETE; | |
448 return connection_->socket() | |
449 ->Write(request_headers_.get(), bytes_remaining, io_callback_); | |
450 } | |
451 | |
452 int HttpStreamParser::DoSendHeadersComplete(int result) { | |
453 if (result < 0) { | |
454 // In the unlikely case that the headers and body were merged, all the | |
455 // the headers were sent, but not all of the body way, and |result| is | |
456 // an error that this should try reading after, stash the error for now and | |
457 // act like the request was successfully sent. | |
458 if (request_headers_->BytesConsumed() >= request_headers_length_ && | |
459 ShouldTryReadingOnUploadError(result)) { | |
460 upload_error_ = result; | |
461 return OK; | |
462 } | |
463 return result; | |
464 } | |
465 | |
466 request_headers_->DidConsume(result); | |
467 if (request_headers_->BytesRemaining() > 0) { | |
468 io_state_ = STATE_SEND_HEADERS; | |
469 return OK; | |
470 } | |
471 | |
472 if (request_->upload_data_stream != NULL && | |
473 (request_->upload_data_stream->is_chunked() || | |
474 // !IsEOF() indicates that the body wasn't merged. | |
475 (request_->upload_data_stream->size() > 0 && | |
476 !request_->upload_data_stream->IsEOF()))) { | |
477 net_log_.AddEvent( | |
478 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_BODY, | |
479 base::Bind(&NetLogSendRequestBodyCallback, | |
480 request_->upload_data_stream->size(), | |
481 request_->upload_data_stream->is_chunked(), | |
482 false /* not merged */)); | |
483 io_state_ = STATE_SEND_BODY; | |
484 return OK; | |
485 } | |
486 | |
487 // Finished sending the request. | |
488 return OK; | |
489 } | |
490 | |
491 int HttpStreamParser::DoSendBody() { | |
492 if (request_body_send_buf_->BytesRemaining() > 0) { | |
493 io_state_ = STATE_SEND_BODY_COMPLETE; | |
494 return connection_->socket() | |
495 ->Write(request_body_send_buf_.get(), | |
496 request_body_send_buf_->BytesRemaining(), | |
497 io_callback_); | |
498 } | |
499 | |
500 if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { | |
501 // Finished sending the request. | |
502 return OK; | |
503 } | |
504 | |
505 request_body_read_buf_->Clear(); | |
506 io_state_ = STATE_SEND_REQUEST_READ_BODY_COMPLETE; | |
507 return request_->upload_data_stream->Read(request_body_read_buf_.get(), | |
508 request_body_read_buf_->capacity(), | |
509 io_callback_); | |
510 } | |
511 | |
512 int HttpStreamParser::DoSendBodyComplete(int result) { | |
513 if (result < 0) { | |
514 // If |result| is an error that this should try reading after, stash the | |
515 // error for now and act like the request was successfully sent. | |
516 if (ShouldTryReadingOnUploadError(result)) { | |
517 upload_error_ = result; | |
518 return OK; | |
519 } | |
520 return result; | |
521 } | |
522 | |
523 request_body_send_buf_->DidConsume(result); | |
524 | |
525 io_state_ = STATE_SEND_BODY; | |
526 return OK; | |
527 } | |
528 | |
529 int HttpStreamParser::DoSendRequestReadBodyComplete(int result) { | |
530 // |result| is the result of read from the request body from the last call to | |
531 // DoSendBody(). | |
532 DCHECK_GE(result, 0); // There won't be errors. | |
533 | |
534 // Chunked data needs to be encoded. | |
535 if (request_->upload_data_stream->is_chunked()) { | |
536 if (result == 0) { // Reached the end. | |
537 DCHECK(request_->upload_data_stream->IsEOF()); | |
538 sent_last_chunk_ = true; | |
539 } | |
540 // Encode the buffer as 1 chunk. | |
541 const base::StringPiece payload(request_body_read_buf_->data(), result); | |
542 request_body_send_buf_->Clear(); | |
543 result = EncodeChunk(payload, | |
544 request_body_send_buf_->data(), | |
545 request_body_send_buf_->capacity()); | |
546 } | |
547 | |
548 if (result == 0) { // Reached the end. | |
549 // Reaching EOF means we can finish sending request body unless the data is | |
550 // chunked. (i.e. No need to send the terminal chunk.) | |
551 DCHECK(request_->upload_data_stream->IsEOF()); | |
552 DCHECK(!request_->upload_data_stream->is_chunked()); | |
553 // Finished sending the request. | |
554 } else if (result > 0) { | |
555 request_body_send_buf_->DidAppend(result); | |
556 result = 0; | |
557 io_state_ = STATE_SEND_BODY; | |
558 } | |
559 return result; | |
560 } | |
561 | |
562 int HttpStreamParser::DoReadHeaders() { | |
563 io_state_ = STATE_READ_HEADERS_COMPLETE; | |
564 | |
565 // Grow the read buffer if necessary. | |
566 if (read_buf_->RemainingCapacity() == 0) | |
567 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); | |
568 | |
569 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. | |
570 // See if the user is passing in an IOBuffer with a NULL |data_|. | |
571 CHECK(read_buf_->data()); | |
572 | |
573 return connection_->socket() | |
574 ->Read(read_buf_.get(), read_buf_->RemainingCapacity(), io_callback_); | |
575 } | |
576 | |
577 int HttpStreamParser::DoReadHeadersComplete(int result) { | |
578 result = HandleReadHeaderResult(result); | |
579 | |
580 // TODO(mmenke): The code below is ugly and hacky. A much better and more | |
581 // flexible long term solution would be to separate out the read and write | |
582 // loops, though this would involve significant changes, both here and | |
583 // elsewhere (WebSockets, for instance). | |
584 | |
585 // If still reading the headers, or there was no error uploading the request | |
586 // body, just return the result. | |
587 if (io_state_ == STATE_READ_HEADERS || upload_error_ == OK) | |
588 return result; | |
589 | |
590 // If the result is ERR_IO_PENDING, |io_state_| should be STATE_READ_HEADERS. | |
591 DCHECK_NE(ERR_IO_PENDING, result); | |
592 | |
593 // On errors, use the original error received when sending the request. | |
594 // The main cases where these are different is when there's a header-related | |
595 // error code, or when there's an ERR_CONNECTION_CLOSED, which can result in | |
596 // special handling of partial responses and HTTP/0.9 responses. | |
597 if (result < 0) { | |
598 // Nothing else to do. In the HTTP/0.9 or only partial headers received | |
599 // cases, can normally go to other states after an error reading headers. | |
600 io_state_ = STATE_DONE; | |
601 // Don't let caller see the headers. | |
602 response_->headers = NULL; | |
603 return upload_error_; | |
604 } | |
605 | |
606 // Skip over 1xx responses as usual, and allow 4xx/5xx error responses to | |
607 // override the error received while uploading the body. | |
608 int response_code_class = response_->headers->response_code() / 100; | |
609 if (response_code_class == 1 || response_code_class == 4 || | |
610 response_code_class == 5) { | |
611 return result; | |
612 } | |
613 | |
614 // All other status codes are not allowed after an error during upload, to | |
615 // make sure the consumer has some indication there was an error. | |
616 | |
617 // Nothing else to do. | |
618 io_state_ = STATE_DONE; | |
619 // Don't let caller see the headers. | |
620 response_->headers = NULL; | |
621 return upload_error_; | |
622 } | |
623 | |
624 int HttpStreamParser::DoReadBody() { | |
625 io_state_ = STATE_READ_BODY_COMPLETE; | |
626 | |
627 // There may be some data left over from reading the response headers. | |
628 if (read_buf_->offset()) { | |
629 int available = read_buf_->offset() - read_buf_unused_offset_; | |
630 if (available) { | |
631 CHECK_GT(available, 0); | |
632 int bytes_from_buffer = std::min(available, user_read_buf_len_); | |
633 memcpy(user_read_buf_->data(), | |
634 read_buf_->StartOfBuffer() + read_buf_unused_offset_, | |
635 bytes_from_buffer); | |
636 read_buf_unused_offset_ += bytes_from_buffer; | |
637 if (bytes_from_buffer == available) { | |
638 read_buf_->SetCapacity(0); | |
639 read_buf_unused_offset_ = 0; | |
640 } | |
641 return bytes_from_buffer; | |
642 } else { | |
643 read_buf_->SetCapacity(0); | |
644 read_buf_unused_offset_ = 0; | |
645 } | |
646 } | |
647 | |
648 // Check to see if we're done reading. | |
649 if (IsResponseBodyComplete()) | |
650 return 0; | |
651 | |
652 DCHECK_EQ(0, read_buf_->offset()); | |
653 return connection_->socket() | |
654 ->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); | |
655 } | |
656 | |
657 int HttpStreamParser::DoReadBodyComplete(int result) { | |
658 // When the connection is closed, there are numerous ways to interpret it. | |
659 // | |
660 // - If a Content-Length header is present and the body contains exactly that | |
661 // number of bytes at connection close, the response is successful. | |
662 // | |
663 // - If a Content-Length header is present and the body contains fewer bytes | |
664 // than promised by the header at connection close, it may indicate that | |
665 // the connection was closed prematurely, or it may indicate that the | |
666 // server sent an invalid Content-Length header. Unfortunately, the invalid | |
667 // Content-Length header case does occur in practice and other browsers are | |
668 // tolerant of it. We choose to treat it as an error for now, but the | |
669 // download system treats it as a non-error, and URLRequestHttpJob also | |
670 // treats it as OK if the Content-Length is the post-decoded body content | |
671 // length. | |
672 // | |
673 // - If chunked encoding is used and the terminating chunk has been processed | |
674 // when the connection is closed, the response is successful. | |
675 // | |
676 // - If chunked encoding is used and the terminating chunk has not been | |
677 // processed when the connection is closed, it may indicate that the | |
678 // connection was closed prematurely or it may indicate that the server | |
679 // sent an invalid chunked encoding. We choose to treat it as | |
680 // an invalid chunked encoding. | |
681 // | |
682 // - If a Content-Length is not present and chunked encoding is not used, | |
683 // connection close is the only way to signal that the response is | |
684 // complete. Unfortunately, this also means that there is no way to detect | |
685 // early close of a connection. No error is returned. | |
686 if (result == 0 && !IsResponseBodyComplete() && CanFindEndOfResponse()) { | |
687 if (chunked_decoder_.get()) | |
688 result = ERR_INCOMPLETE_CHUNKED_ENCODING; | |
689 else | |
690 result = ERR_CONTENT_LENGTH_MISMATCH; | |
691 } | |
692 | |
693 if (result > 0) | |
694 received_bytes_ += result; | |
695 | |
696 // Filter incoming data if appropriate. FilterBuf may return an error. | |
697 if (result > 0 && chunked_decoder_.get()) { | |
698 result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result); | |
699 if (result == 0 && !chunked_decoder_->reached_eof()) { | |
700 // Don't signal completion of the Read call yet or else it'll look like | |
701 // we received end-of-file. Wait for more data. | |
702 io_state_ = STATE_READ_BODY; | |
703 return OK; | |
704 } | |
705 } | |
706 | |
707 if (result > 0) | |
708 response_body_read_ += result; | |
709 | |
710 if (result <= 0 || IsResponseBodyComplete()) { | |
711 io_state_ = STATE_DONE; | |
712 | |
713 // Save the overflow data, which can be in two places. There may be | |
714 // some left over in |user_read_buf_|, plus there may be more | |
715 // in |read_buf_|. But the part left over in |user_read_buf_| must have | |
716 // come from the |read_buf_|, so there's room to put it back at the | |
717 // start first. | |
718 int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; | |
719 int save_amount = 0; | |
720 if (chunked_decoder_.get()) { | |
721 save_amount = chunked_decoder_->bytes_after_eof(); | |
722 } else if (response_body_length_ >= 0) { | |
723 int64 extra_data_read = response_body_read_ - response_body_length_; | |
724 if (extra_data_read > 0) { | |
725 save_amount = static_cast<int>(extra_data_read); | |
726 if (result > 0) | |
727 result -= save_amount; | |
728 } | |
729 } | |
730 | |
731 CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); | |
732 if (read_buf_->capacity() < save_amount + additional_save_amount) { | |
733 read_buf_->SetCapacity(save_amount + additional_save_amount); | |
734 } | |
735 | |
736 if (save_amount) { | |
737 received_bytes_ -= save_amount; | |
738 memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, | |
739 save_amount); | |
740 } | |
741 read_buf_->set_offset(save_amount); | |
742 if (additional_save_amount) { | |
743 memmove(read_buf_->data(), | |
744 read_buf_->StartOfBuffer() + read_buf_unused_offset_, | |
745 additional_save_amount); | |
746 read_buf_->set_offset(save_amount + additional_save_amount); | |
747 } | |
748 read_buf_unused_offset_ = 0; | |
749 } else { | |
750 // Now waiting for more of the body to be read. | |
751 user_read_buf_ = NULL; | |
752 user_read_buf_len_ = 0; | |
753 } | |
754 | |
755 return result; | |
756 } | |
757 | |
758 int HttpStreamParser::HandleReadHeaderResult(int result) { | |
759 DCHECK_EQ(0, read_buf_unused_offset_); | |
760 | |
761 if (result == 0) | |
762 result = ERR_CONNECTION_CLOSED; | |
763 | |
764 if (result < 0 && result != ERR_CONNECTION_CLOSED) { | |
765 io_state_ = STATE_DONE; | |
766 return result; | |
767 } | |
768 // If we've used the connection before, then we know it is not a HTTP/0.9 | |
769 // response and return ERR_CONNECTION_CLOSED. | |
770 if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && | |
771 connection_->is_reused()) { | |
772 io_state_ = STATE_DONE; | |
773 return result; | |
774 } | |
775 | |
776 // Record our best estimate of the 'response time' as the time when we read | |
777 // the first bytes of the response headers. | |
778 if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) | |
779 response_->response_time = base::Time::Now(); | |
780 | |
781 if (result == ERR_CONNECTION_CLOSED) { | |
782 // The connection closed before we detected the end of the headers. | |
783 if (read_buf_->offset() == 0) { | |
784 // The connection was closed before any data was sent. Likely an error | |
785 // rather than empty HTTP/0.9 response. | |
786 io_state_ = STATE_DONE; | |
787 return ERR_EMPTY_RESPONSE; | |
788 } else if (request_->url.SchemeIsSecure()) { | |
789 // The connection was closed in the middle of the headers. For HTTPS we | |
790 // don't parse partial headers. Return a different error code so that we | |
791 // know that we shouldn't attempt to retry the request. | |
792 io_state_ = STATE_DONE; | |
793 return ERR_RESPONSE_HEADERS_TRUNCATED; | |
794 } | |
795 // Parse things as well as we can and let the caller decide what to do. | |
796 int end_offset; | |
797 if (response_header_start_offset_ >= 0) { | |
798 io_state_ = STATE_READ_BODY_COMPLETE; | |
799 end_offset = read_buf_->offset(); | |
800 } else { | |
801 // Now waiting for the body to be read. | |
802 end_offset = 0; | |
803 } | |
804 int rv = DoParseResponseHeaders(end_offset); | |
805 if (rv < 0) | |
806 return rv; | |
807 return result; | |
808 } | |
809 | |
810 read_buf_->set_offset(read_buf_->offset() + result); | |
811 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); | |
812 DCHECK_GE(result, 0); | |
813 | |
814 int end_of_header_offset = ParseResponseHeaders(); | |
815 | |
816 // Note: -1 is special, it indicates we haven't found the end of headers. | |
817 // Anything less than -1 is a net::Error, so we bail out. | |
818 if (end_of_header_offset < -1) | |
819 return end_of_header_offset; | |
820 | |
821 if (end_of_header_offset == -1) { | |
822 io_state_ = STATE_READ_HEADERS; | |
823 // Prevent growing the headers buffer indefinitely. | |
824 if (read_buf_->offset() >= kMaxHeaderBufSize) { | |
825 io_state_ = STATE_DONE; | |
826 return ERR_RESPONSE_HEADERS_TOO_BIG; | |
827 } | |
828 } else { | |
829 CalculateResponseBodySize(); | |
830 // If the body is zero length, the caller may not call ReadResponseBody, | |
831 // which is where any extra data is copied to read_buf_, so we move the | |
832 // data here. | |
833 if (response_body_length_ == 0) { | |
834 int extra_bytes = read_buf_->offset() - end_of_header_offset; | |
835 if (extra_bytes) { | |
836 CHECK_GT(extra_bytes, 0); | |
837 memmove(read_buf_->StartOfBuffer(), | |
838 read_buf_->StartOfBuffer() + end_of_header_offset, | |
839 extra_bytes); | |
840 } | |
841 read_buf_->SetCapacity(extra_bytes); | |
842 if (response_->headers->response_code() / 100 == 1) { | |
843 // After processing a 1xx response, the caller will ask for the next | |
844 // header, so reset state to support that. We don't completely ignore a | |
845 // 1xx response because it cannot be returned in reply to a CONNECT | |
846 // request so we return OK here, which lets the caller inspect the | |
847 // response and reject it in the event that we're setting up a CONNECT | |
848 // tunnel. | |
849 response_header_start_offset_ = -1; | |
850 response_body_length_ = -1; | |
851 // Now waiting for the second set of headers to be read. | |
852 } else { | |
853 io_state_ = STATE_DONE; | |
854 } | |
855 return OK; | |
856 } | |
857 | |
858 // Note where the headers stop. | |
859 read_buf_unused_offset_ = end_of_header_offset; | |
860 // Now waiting for the body to be read. | |
861 } | |
862 return result; | |
863 } | |
864 | |
865 int HttpStreamParser::ParseResponseHeaders() { | |
866 int end_offset = -1; | |
867 DCHECK_EQ(0, read_buf_unused_offset_); | |
868 | |
869 // Look for the start of the status line, if it hasn't been found yet. | |
870 if (response_header_start_offset_ < 0) { | |
871 response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( | |
872 read_buf_->StartOfBuffer(), read_buf_->offset()); | |
873 } | |
874 | |
875 if (response_header_start_offset_ >= 0) { | |
876 end_offset = HttpUtil::LocateEndOfHeaders(read_buf_->StartOfBuffer(), | |
877 read_buf_->offset(), | |
878 response_header_start_offset_); | |
879 } else if (read_buf_->offset() >= 8) { | |
880 // Enough data to decide that this is an HTTP/0.9 response. | |
881 // 8 bytes = (4 bytes of junk) + "http".length() | |
882 end_offset = 0; | |
883 } | |
884 | |
885 if (end_offset == -1) | |
886 return -1; | |
887 | |
888 int rv = DoParseResponseHeaders(end_offset); | |
889 if (rv < 0) | |
890 return rv; | |
891 return end_offset; | |
892 } | |
893 | |
894 int HttpStreamParser::DoParseResponseHeaders(int end_offset) { | |
895 scoped_refptr<HttpResponseHeaders> headers; | |
896 DCHECK_EQ(0, read_buf_unused_offset_); | |
897 | |
898 if (response_header_start_offset_ >= 0) { | |
899 received_bytes_ += end_offset; | |
900 headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( | |
901 read_buf_->StartOfBuffer(), end_offset)); | |
902 } else { | |
903 // Enough data was read -- there is no status line. | |
904 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); | |
905 } | |
906 | |
907 // Check for multiple Content-Length headers with no Transfer-Encoding header. | |
908 // If they exist, and have distinct values, it's a potential response | |
909 // smuggling attack. | |
910 if (!headers->HasHeader("Transfer-Encoding")) { | |
911 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) | |
912 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; | |
913 } | |
914 | |
915 // Check for multiple Content-Disposition or Location headers. If they exist, | |
916 // it's also a potential response smuggling attack. | |
917 if (HeadersContainMultipleCopiesOfField(*headers.get(), | |
918 "Content-Disposition")) | |
919 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; | |
920 if (HeadersContainMultipleCopiesOfField(*headers.get(), "Location")) | |
921 return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; | |
922 | |
923 response_->headers = headers; | |
924 response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; | |
925 response_->vary_data.Init(*request_, *response_->headers.get()); | |
926 DVLOG(1) << __FUNCTION__ << "()" | |
927 << " content_length = \"" << response_->headers->GetContentLength() | |
928 << "\n\"" | |
929 << " headers = \"" | |
930 << GetResponseHeaderLines(*response_->headers.get()) << "\""; | |
931 return OK; | |
932 } | |
933 | |
934 void HttpStreamParser::CalculateResponseBodySize() { | |
935 // Figure how to determine EOF: | |
936 | |
937 // For certain responses, we know the content length is always 0. From | |
938 // RFC 2616 Section 4.3 Message Body: | |
939 // | |
940 // For response messages, whether or not a message-body is included with | |
941 // a message is dependent on both the request method and the response | |
942 // status code (section 6.1.1). All responses to the HEAD request method | |
943 // MUST NOT include a message-body, even though the presence of entity- | |
944 // header fields might lead one to believe they do. All 1xx | |
945 // (informational), 204 (no content), and 304 (not modified) responses | |
946 // MUST NOT include a message-body. All other responses do include a | |
947 // message-body, although it MAY be of zero length. | |
948 if (response_->headers->response_code() / 100 == 1) { | |
949 response_body_length_ = 0; | |
950 } else { | |
951 switch (response_->headers->response_code()) { | |
952 case 204: // No Content | |
953 case 205: // Reset Content | |
954 case 304: // Not Modified | |
955 response_body_length_ = 0; | |
956 break; | |
957 } | |
958 } | |
959 if (request_->method == "HEAD") | |
960 response_body_length_ = 0; | |
961 | |
962 if (response_body_length_ == -1) { | |
963 // "Transfer-Encoding: chunked" trumps "Content-Length: N" | |
964 if (response_->headers->IsChunkEncoded()) { | |
965 chunked_decoder_.reset(new HttpChunkedDecoder()); | |
966 } else { | |
967 response_body_length_ = response_->headers->GetContentLength(); | |
968 // If response_body_length_ is still -1, then we have to wait | |
969 // for the server to close the connection. | |
970 } | |
971 } | |
972 } | |
973 | |
974 UploadProgress HttpStreamParser::GetUploadProgress() const { | |
975 if (!request_->upload_data_stream) | |
976 return UploadProgress(); | |
977 | |
978 return UploadProgress(request_->upload_data_stream->position(), | |
979 request_->upload_data_stream->size()); | |
980 } | |
981 | |
982 bool HttpStreamParser::IsResponseBodyComplete() const { | |
983 if (chunked_decoder_.get()) | |
984 return chunked_decoder_->reached_eof(); | |
985 if (response_body_length_ != -1) | |
986 return response_body_read_ >= response_body_length_; | |
987 | |
988 return false; // Must read to EOF. | |
989 } | |
990 | |
991 bool HttpStreamParser::CanFindEndOfResponse() const { | |
992 return chunked_decoder_.get() || response_body_length_ >= 0; | |
993 } | |
994 | |
995 bool HttpStreamParser::IsMoreDataBuffered() const { | |
996 return read_buf_->offset() > read_buf_unused_offset_; | |
997 } | |
998 | |
999 bool HttpStreamParser::IsConnectionReused() const { | |
1000 ClientSocketHandle::SocketReuseType reuse_type = connection_->reuse_type(); | |
1001 return connection_->is_reused() || | |
1002 reuse_type == ClientSocketHandle::UNUSED_IDLE; | |
1003 } | |
1004 | |
1005 void HttpStreamParser::SetConnectionReused() { | |
1006 connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); | |
1007 } | |
1008 | |
1009 bool HttpStreamParser::IsConnectionReusable() const { | |
1010 return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); | |
1011 } | |
1012 | |
1013 void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { | |
1014 if (request_->url.SchemeIsSecure() && connection_->socket()) { | |
1015 SSLClientSocket* ssl_socket = | |
1016 static_cast<SSLClientSocket*>(connection_->socket()); | |
1017 ssl_socket->GetSSLInfo(ssl_info); | |
1018 } | |
1019 } | |
1020 | |
1021 void HttpStreamParser::GetSSLCertRequestInfo( | |
1022 SSLCertRequestInfo* cert_request_info) { | |
1023 if (request_->url.SchemeIsSecure() && connection_->socket()) { | |
1024 SSLClientSocket* ssl_socket = | |
1025 static_cast<SSLClientSocket*>(connection_->socket()); | |
1026 ssl_socket->GetSSLCertRequestInfo(cert_request_info); | |
1027 } | |
1028 } | |
1029 | |
1030 int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, | |
1031 char* output, | |
1032 size_t output_size) { | |
1033 if (output_size < payload.size() + kChunkHeaderFooterSize) | |
1034 return ERR_INVALID_ARGUMENT; | |
1035 | |
1036 char* cursor = output; | |
1037 // Add the header. | |
1038 const int num_chars = base::snprintf(output, output_size, | |
1039 "%X\r\n", | |
1040 static_cast<int>(payload.size())); | |
1041 cursor += num_chars; | |
1042 // Add the payload if any. | |
1043 if (payload.size() > 0) { | |
1044 memcpy(cursor, payload.data(), payload.size()); | |
1045 cursor += payload.size(); | |
1046 } | |
1047 // Add the trailing CRLF. | |
1048 memcpy(cursor, "\r\n", 2); | |
1049 cursor += 2; | |
1050 | |
1051 return cursor - output; | |
1052 } | |
1053 | |
1054 // static | |
1055 bool HttpStreamParser::ShouldMergeRequestHeadersAndBody( | |
1056 const std::string& request_headers, | |
1057 const UploadDataStream* request_body) { | |
1058 if (request_body != NULL && | |
1059 // IsInMemory() ensures that the request body is not chunked. | |
1060 request_body->IsInMemory() && | |
1061 request_body->size() > 0) { | |
1062 uint64 merged_size = request_headers.size() + request_body->size(); | |
1063 if (merged_size <= kMaxMergedHeaderAndBodySize) | |
1064 return true; | |
1065 } | |
1066 return false; | |
1067 } | |
1068 | |
1069 } // namespace net | |
OLD | NEW |