1 // Copyright (c) 2011 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/compiler_specific.h" 8 #include "base/metrics/histogram.h" 9 #include "base/string_util.h" 10 #include "net/base/address_list.h" 11 #include "net/base/auth.h" 12 #include "net/base/io_buffer.h" 13 #include "net/base/ssl_cert_request_info.h" 14 #include "net/http/http_net_log_params.h" 15 #include "net/http/http_request_headers.h" 16 #include "net/http/http_request_info.h" 17 #include "net/http/http_response_headers.h" 18 #include "net/http/http_util.h" 19 #include "net/socket/ssl_client_socket.h" 20 #include "net/socket/client_socket_handle.h" 21 22 namespace net { 23 24 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, 25 const HttpRequestInfo* request, 26 GrowableIOBuffer* read_buffer, 27 const BoundNetLog& net_log) 28 : io_state_(STATE_NONE), 29 request_(request), 30 request_headers_(NULL), 31 request_body_(NULL), 32 read_buf_(read_buffer), 33 read_buf_unused_offset_(0), 34 response_header_start_offset_(-1), 35 response_body_length_(-1), 36 response_body_read_(0), 37 chunked_decoder_(NULL), 38 user_read_buf_(NULL), 39 user_read_buf_len_(0), 40 user_callback_(NULL), 41 connection_(connection), 42 net_log_(net_log), 43 ALLOW_THIS_IN_INITIALIZER_LIST( 44 io_callback_(this, &HttpStreamParser::OnIOComplete)), 45 chunk_length_(0), 46 chunk_length_without_encoding_(0), 47 sent_last_chunk_(false) { 48 DCHECK_EQ(0, read_buffer->offset()); 49 } 50 51 HttpStreamParser::~HttpStreamParser() { 52 if (request_body_ != NULL && request_body_->is_chunked()) 53 request_body_->set_chunk_callback(NULL); 54 } 55 56 int HttpStreamParser::SendRequest(const std::string& request_line, 57 const HttpRequestHeaders& headers, 58 UploadDataStream* request_body, 59 HttpResponseInfo* response, 60 CompletionCallback* callback) { 61 DCHECK_EQ(STATE_NONE, io_state_); 62 DCHECK(!user_callback_); 63 DCHECK(callback); 64 DCHECK(response); 65 66 if (net_log_.IsLoggingAllEvents()) { 67 net_log_.AddEvent( 68 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 69 make_scoped_refptr(new NetLogHttpRequestParameter( 70 request_line, headers))); 71 } 72 response_ = response; 73 74 // Put the peer's IP address and port into the response. 75 AddressList address; 76 int result = connection_->socket()->GetPeerAddress(&address); 77 if (result != OK) 78 return result; 79 response_->socket_address = HostPortPair::FromAddrInfo(address.head()); 80 81 std::string request = request_line + headers.ToString(); 82 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); 83 request_headers_ = new DrainableIOBuffer(headers_io_buf, 84 headers_io_buf->size()); 85 request_body_.reset(request_body); 86 if (request_body_ != NULL && request_body_->is_chunked()) { 87 request_body_->set_chunk_callback(this); 88 const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. 89 chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + 90 kChunkHeaderFooterSize); 91 } 92 93 io_state_ = STATE_SENDING_HEADERS; 94 result = DoLoop(OK); 95 if (result == ERR_IO_PENDING) 96 user_callback_ = callback; 97 98 return result > 0 ? OK : result; 99 } 100 101 int HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) { 102 DCHECK(io_state_ == STATE_REQUEST_SENT || io_state_ == STATE_DONE); 103 DCHECK(!user_callback_); 104 DCHECK(callback); 105 106 // This function can be called with io_state_ == STATE_DONE if the 107 // connection is closed after seeing just a 1xx response code. 108 if (io_state_ == STATE_DONE) 109 return ERR_CONNECTION_CLOSED; 110 111 int result = OK; 112 io_state_ = STATE_READ_HEADERS; 113 114 if (read_buf_->offset() > 0) { 115 // Simulate the state where the data was just read from the socket. 116 result = read_buf_->offset() - read_buf_unused_offset_; 117 read_buf_->set_offset(read_buf_unused_offset_); 118 } 119 if (result > 0) 120 io_state_ = STATE_READ_HEADERS_COMPLETE; 121 122 result = DoLoop(result); 123 if (result == ERR_IO_PENDING) 124 user_callback_ = callback; 125 126 return result > 0 ? OK : result; 127 } 128 129 void HttpStreamParser::Close(bool not_reusable) { 130 if (not_reusable && connection_->socket()) 131 connection_->socket()->Disconnect(); 132 connection_->Reset(); 133 } 134 135 int HttpStreamParser::ReadResponseBody(IOBuffer* buf, int buf_len, 136 CompletionCallback* callback) { 137 DCHECK(io_state_ == STATE_BODY_PENDING || io_state_ == STATE_DONE); 138 DCHECK(!user_callback_); 139 DCHECK(callback); 140 DCHECK_LE(buf_len, kMaxBufSize); 141 142 if (io_state_ == STATE_DONE) 143 return OK; 144 145 user_read_buf_ = buf; 146 user_read_buf_len_ = buf_len; 147 io_state_ = STATE_READ_BODY; 148 149 int result = DoLoop(OK); 150 if (result == ERR_IO_PENDING) 151 user_callback_ = callback; 152 153 return result; 154 } 155 156 void HttpStreamParser::OnIOComplete(int result) { 157 result = DoLoop(result); 158 159 // The client callback can do anything, including destroying this class, 160 // so any pending callback must be issued after everything else is done. 161 if (result != ERR_IO_PENDING && user_callback_) { 162 CompletionCallback* c = user_callback_; 163 user_callback_ = NULL; 164 c->Run(result); 165 } 166 } 167 168 void HttpStreamParser::OnChunkAvailable() { 169 // This method may get called while sending the headers or body, so check 170 // before processing the new data. If we were still initializing or sending 171 // headers, we will automatically start reading the chunks once we get into 172 // STATE_SENDING_BODY so nothing to do here. 173 DCHECK(io_state_ == STATE_SENDING_HEADERS || io_state_ == STATE_SENDING_BODY); 174 if (io_state_ == STATE_SENDING_BODY) 175 OnIOComplete(0); 176 } 177 178 int HttpStreamParser::DoLoop(int result) { 179 bool can_do_more = true; 180 do { 181 switch (io_state_) { 182 case STATE_SENDING_HEADERS: 183 if (result < 0) 184 can_do_more = false; 185 else 186 result = DoSendHeaders(result); 187 break; 188 case STATE_SENDING_BODY: 189 if (result < 0) 190 can_do_more = false; 191 else 192 result = DoSendBody(result); 193 break; 194 case STATE_REQUEST_SENT: 195 DCHECK(result != ERR_IO_PENDING); 196 can_do_more = false; 197 break; 198 case STATE_READ_HEADERS: 199 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, NULL); 200 result = DoReadHeaders(); 201 break; 202 case STATE_READ_HEADERS_COMPLETE: 203 result = DoReadHeadersComplete(result); 204 net_log_.EndEventWithNetErrorCode( 205 NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS, result); 206 break; 207 case STATE_BODY_PENDING: 208 DCHECK(result != ERR_IO_PENDING); 209 can_do_more = false; 210 break; 211 case STATE_READ_BODY: 212 result = DoReadBody(); 213 // DoReadBodyComplete handles error conditions. 214 break; 215 case STATE_READ_BODY_COMPLETE: 216 result = DoReadBodyComplete(result); 217 break; 218 case STATE_DONE: 219 DCHECK(result != ERR_IO_PENDING); 220 can_do_more = false; 221 break; 222 default: 223 NOTREACHED(); 224 can_do_more = false; 225 break; 226 } 227 } while (result != ERR_IO_PENDING && can_do_more); 228 229 return result; 230 } 231 232 int HttpStreamParser::DoSendHeaders(int result) { 233 request_headers_->DidConsume(result); 234 int bytes_remaining = request_headers_->BytesRemaining(); 235 if (bytes_remaining > 0) { 236 // Record our best estimate of the 'request time' as the time when we send 237 // out the first bytes of the request headers. 238 if (bytes_remaining == request_headers_->size()) { 239 response_->request_time = base::Time::Now(); 240 241 // We'll record the count of uncoalesced packets IFF coalescing will help, 242 // and otherwise we'll use an enum to tell why it won't help. 243 enum COALESCE_POTENTIAL { 244 // Coalescing won't reduce packet count. 245 NO_ADVANTAGE = 0, 246 // There is only a header packet or we have a request body but the 247 // request body isn't available yet (can't coalesce). 248 HEADER_ONLY = 1, 249 // Various cases of coalasced savings. 250 COALESCE_POTENTIAL_MAX = 30 251 }; 252 size_t coalesce = HEADER_ONLY; 253 if (request_body_ != NULL && !request_body_->is_chunked()) { 254 const size_t kBytesPerPacket = 1430; 255 uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) / 256 kBytesPerPacket; 257 uint64 header_packets = (bytes_remaining + kBytesPerPacket - 1) / 258 kBytesPerPacket; 259 uint64 coalesced_packets = (request_body_->size() + bytes_remaining + 260 kBytesPerPacket - 1) / kBytesPerPacket; 261 if (coalesced_packets < header_packets + body_packets) { 262 if (coalesced_packets > COALESCE_POTENTIAL_MAX) 263 coalesce = COALESCE_POTENTIAL_MAX; 264 else 265 coalesce = static_cast<size_t>(header_packets + body_packets); 266 } else { 267 coalesce = NO_ADVANTAGE; 268 } 269 } 270 UMA_HISTOGRAM_ENUMERATION("Net.CoalescePotential", coalesce, 271 COALESCE_POTENTIAL_MAX); 272 } 273 result = connection_->socket()->Write(request_headers_, 274 bytes_remaining, 275 &io_callback_); 276 } else if (request_body_ != NULL && 277 (request_body_->is_chunked() || request_body_->size())) { 278 io_state_ = STATE_SENDING_BODY; 279 result = OK; 280 } else { 281 io_state_ = STATE_REQUEST_SENT; 282 } 283 return result; 284 } 285 286 int HttpStreamParser::DoSendBody(int result) { 287 if (request_body_->is_chunked()) { 288 chunk_length_ -= result; 289 if (chunk_length_) { 290 memmove(chunk_buf_->data(), chunk_buf_->data() + result, chunk_length_); 291 return connection_->socket()->Write(chunk_buf_, chunk_length_, 292 &io_callback_); 293 } 294 295 if (sent_last_chunk_) { 296 io_state_ = STATE_REQUEST_SENT; 297 return OK; 298 } 299 300 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); 301 chunk_length_without_encoding_ = 0; 302 chunk_length_ = 0; 303 304 int buf_len = static_cast<int>(request_body_->buf_len()); 305 if (request_body_->eof()) { 306 static const char kLastChunk[] = "0\r\n\r\n"; 307 chunk_length_ = strlen(kLastChunk); 308 memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); 309 sent_last_chunk_ = true; 310 } else if (buf_len) { 311 // Encode and send the buffer as 1 chunk. 312 std::string chunk_header = StringPrintf("%X\r\n", buf_len); 313 char* chunk_ptr = chunk_buf_->data(); 314 memcpy(chunk_ptr, chunk_header.data(), chunk_header.length()); 315 chunk_ptr += chunk_header.length(); 316 memcpy(chunk_ptr, request_body_->buf()->data(), buf_len); 317 chunk_ptr += buf_len; 318 memcpy(chunk_ptr, "\r\n", 2); 319 chunk_length_without_encoding_ = buf_len; 320 chunk_length_ = chunk_header.length() + buf_len + 2; 321 } 322 323 if (!chunk_length_) // More POST data is yet to come? 324 return ERR_IO_PENDING; 325 326 return connection_->socket()->Write(chunk_buf_, chunk_length_, 327 &io_callback_); 328 } 329 330 // Non-chunked request body. 331 request_body_->MarkConsumedAndFillBuffer(result); 332 333 if (!request_body_->eof()) { 334 int buf_len = static_cast<int>(request_body_->buf_len()); 335 result = connection_->socket()->Write(request_body_->buf(), buf_len, 336 &io_callback_); 337 } else { 338 io_state_ = STATE_REQUEST_SENT; 339 } 340 return result; 341 } 342 343 int HttpStreamParser::DoReadHeaders() { 344 io_state_ = STATE_READ_HEADERS_COMPLETE; 345 346 // Grow the read buffer if necessary. 347 if (read_buf_->RemainingCapacity() == 0) 348 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 349 350 // http://crbug.com/16371: We're seeing |user_buf_->data()| return NULL. 351 // See if the user is passing in an IOBuffer with a NULL |data_|. 352 CHECK(read_buf_->data()); 353 354 return connection_->socket()->Read(read_buf_, 355 read_buf_->RemainingCapacity(), 356 &io_callback_); 357 } 358 359 int HttpStreamParser::DoReadHeadersComplete(int result) { 360 if (result == 0) 361 result = ERR_CONNECTION_CLOSED; 362 363 if (result < 0 && result != ERR_CONNECTION_CLOSED) { 364 io_state_ = STATE_DONE; 365 return result; 366 } 367 // If we've used the connection before, then we know it is not a HTTP/0.9 368 // response and return ERR_CONNECTION_CLOSED. 369 if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && 370 connection_->is_reused()) { 371 io_state_ = STATE_DONE; 372 return result; 373 } 374 375 // Record our best estimate of the 'response time' as the time when we read 376 // the first bytes of the response headers. 377 if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) 378 response_->response_time = base::Time::Now(); 379 380 if (result == ERR_CONNECTION_CLOSED) { 381 // The connection closed before we detected the end of the headers. 382 // parse things as well as we can and let the caller decide what to do. 383 if (read_buf_->offset() == 0) { 384 // The connection was closed before any data was sent. Likely an error 385 // rather than empty HTTP/0.9 response. 386 io_state_ = STATE_DONE; 387 return ERR_EMPTY_RESPONSE; 388 } else { 389 int end_offset; 390 if (response_header_start_offset_ >= 0) { 391 io_state_ = STATE_READ_BODY_COMPLETE; 392 end_offset = read_buf_->offset(); 393 } else { 394 io_state_ = STATE_BODY_PENDING; 395 end_offset = 0; 396 } 397 int rv = DoParseResponseHeaders(end_offset); 398 if (rv < 0) 399 return rv; 400 return result; 401 } 402 } 403 404 read_buf_->set_offset(read_buf_->offset() + result); 405 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); 406 DCHECK_GE(result, 0); 407 408 int end_of_header_offset = ParseResponseHeaders(); 409 410 // Note: -1 is special, it indicates we haven't found the end of headers. 411 // Anything less than -1 is a net::Error, so we bail out. 412 if (end_of_header_offset < -1) 413 return end_of_header_offset; 414 415 if (end_of_header_offset == -1) { 416 io_state_ = STATE_READ_HEADERS; 417 // Prevent growing the headers buffer indefinitely. 418 if (read_buf_->offset() - read_buf_unused_offset_ >= kMaxHeaderBufSize) { 419 io_state_ = STATE_DONE; 420 return ERR_RESPONSE_HEADERS_TOO_BIG; 421 } 422 } else { 423 // Note where the headers stop. 424 read_buf_unused_offset_ = end_of_header_offset; 425 426 if (response_->headers->response_code() / 100 == 1) { 427 // After processing a 1xx response, the caller will ask for the next 428 // header, so reset state to support that. We don't just skip these 429 // completely because 1xx codes aren't acceptable when establishing a 430 // tunnel. 431 io_state_ = STATE_REQUEST_SENT; 432 response_header_start_offset_ = -1; 433 } else { 434 io_state_ = STATE_BODY_PENDING; 435 CalculateResponseBodySize(); 436 // If the body is 0, the caller may not call ReadResponseBody, which 437 // is where any extra data is copied to read_buf_, so we move the 438 // data here and transition to DONE. 439 if (response_body_length_ == 0) { 440 io_state_ = STATE_DONE; 441 int extra_bytes = read_buf_->offset() - read_buf_unused_offset_; 442 if (extra_bytes) { 443 CHECK_GT(extra_bytes, 0); 444 memmove(read_buf_->StartOfBuffer(), 445 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 446 extra_bytes); 447 } 448 read_buf_->SetCapacity(extra_bytes); 449 read_buf_unused_offset_ = 0; 450 return OK; 451 } 452 } 453 } 454 return result; 455 } 456 457 int HttpStreamParser::DoReadBody() { 458 io_state_ = STATE_READ_BODY_COMPLETE; 459 460 // There may be some data left over from reading the response headers. 461 if (read_buf_->offset()) { 462 int available = read_buf_->offset() - read_buf_unused_offset_; 463 if (available) { 464 CHECK_GT(available, 0); 465 int bytes_from_buffer = std::min(available, user_read_buf_len_); 466 memcpy(user_read_buf_->data(), 467 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 468 bytes_from_buffer); 469 read_buf_unused_offset_ += bytes_from_buffer; 470 if (bytes_from_buffer == available) { 471 read_buf_->SetCapacity(0); 472 read_buf_unused_offset_ = 0; 473 } 474 return bytes_from_buffer; 475 } else { 476 read_buf_->SetCapacity(0); 477 read_buf_unused_offset_ = 0; 478 } 479 } 480 481 // Check to see if we're done reading. 482 if (IsResponseBodyComplete()) 483 return 0; 484 485 DCHECK_EQ(0, read_buf_->offset()); 486 return connection_->socket()->Read(user_read_buf_, user_read_buf_len_, 487 &io_callback_); 488 } 489 490 int HttpStreamParser::DoReadBodyComplete(int result) { 491 // If we didn't get a content-length and aren't using a chunked encoding, 492 // the only way to signal the end of a stream is to close the connection, 493 // so we don't treat that as an error, though in some cases we may not 494 // have completely received the resource. 495 if (result == 0 && !IsResponseBodyComplete() && CanFindEndOfResponse()) 496 result = ERR_CONNECTION_CLOSED; 497 498 // Filter incoming data if appropriate. FilterBuf may return an error. 499 if (result > 0 && chunked_decoder_.get()) { 500 result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result); 501 if (result == 0 && !chunked_decoder_->reached_eof()) { 502 // Don't signal completion of the Read call yet or else it'll look like 503 // we received end-of-file. Wait for more data. 504 io_state_ = STATE_READ_BODY; 505 return OK; 506 } 507 } 508 509 if (result > 0) 510 response_body_read_ += result; 511 512 if (result <= 0 || IsResponseBodyComplete()) { 513 io_state_ = STATE_DONE; 514 515 // Save the overflow data, which can be in two places. There may be 516 // some left over in |user_read_buf_|, plus there may be more 517 // in |read_buf_|. But the part left over in |user_read_buf_| must have 518 // come from the |read_buf_|, so there's room to put it back at the 519 // start first. 520 int additional_save_amount = read_buf_->offset() - read_buf_unused_offset_; 521 int save_amount = 0; 522 if (chunked_decoder_.get()) { 523 save_amount = chunked_decoder_->bytes_after_eof(); 524 } else if (response_body_length_ >= 0) { 525 int64 extra_data_read = response_body_read_ - response_body_length_; 526 if (extra_data_read > 0) { 527 save_amount = static_cast<int>(extra_data_read); 528 if (result > 0) 529 result -= save_amount; 530 } 531 } 532 533 CHECK_LE(save_amount + additional_save_amount, kMaxBufSize); 534 if (read_buf_->capacity() < save_amount + additional_save_amount) { 535 read_buf_->SetCapacity(save_amount + additional_save_amount); 536 } 537 538 if (save_amount) { 539 memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result, 540 save_amount); 541 } 542 read_buf_->set_offset(save_amount); 543 if (additional_save_amount) { 544 memmove(read_buf_->data(), 545 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 546 additional_save_amount); 547 read_buf_->set_offset(save_amount + additional_save_amount); 548 } 549 read_buf_unused_offset_ = 0; 550 } else { 551 io_state_ = STATE_BODY_PENDING; 552 user_read_buf_ = NULL; 553 user_read_buf_len_ = 0; 554 } 555 556 return result; 557 } 558 559 int HttpStreamParser::ParseResponseHeaders() { 560 int end_offset = -1; 561 562 // Look for the start of the status line, if it hasn't been found yet. 563 if (response_header_start_offset_ < 0) { 564 response_header_start_offset_ = HttpUtil::LocateStartOfStatusLine( 565 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 566 read_buf_->offset() - read_buf_unused_offset_); 567 } 568 569 if (response_header_start_offset_ >= 0) { 570 end_offset = HttpUtil::LocateEndOfHeaders( 571 read_buf_->StartOfBuffer() + read_buf_unused_offset_, 572 read_buf_->offset() - read_buf_unused_offset_, 573 response_header_start_offset_); 574 } else if (read_buf_->offset() - read_buf_unused_offset_ >= 8) { 575 // Enough data to decide that this is an HTTP/0.9 response. 576 // 8 bytes = (4 bytes of junk) + "http".length() 577 end_offset = 0; 578 } 579 580 if (end_offset == -1) 581 return -1; 582 583 int rv = DoParseResponseHeaders(end_offset); 584 if (rv < 0) 585 return rv; 586 return end_offset + read_buf_unused_offset_; 587 } 588 589 int HttpStreamParser::DoParseResponseHeaders(int end_offset) { 590 scoped_refptr<HttpResponseHeaders> headers; 591 if (response_header_start_offset_ >= 0) { 592 headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( 593 read_buf_->StartOfBuffer() + read_buf_unused_offset_, end_offset)); 594 } else { 595 // Enough data was read -- there is no status line. 596 headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); 597 } 598 599 // Check for multiple Content-Length headers with a Transfer-Encoding header. 600 // If they exist, it's a potential response smuggling attack. 601 602 void* it = NULL; 603 const std::string content_length_header("Content-Length"); 604 std::string content_length_value; 605 if (!headers->HasHeader("Transfer-Encoding") && 606 headers->EnumerateHeader( 607 &it, content_length_header, &content_length_value)) { 608 // Ok, there's no Transfer-Encoding header and there's at least one 609 // Content-Length header. Check if there are any more Content-Length 610 // headers, and if so, make sure they have the same value. Otherwise, it's 611 // a possible response smuggling attack. 612 std::string content_length_value2; 613 while (headers->EnumerateHeader( 614 &it, content_length_header, &content_length_value2)) { 615 if (content_length_value != content_length_value2) 616 return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; 617 } 618 } 619 620 response_->headers = headers; 621 response_->vary_data.Init(*request_, *response_->headers); 622 return OK; 623 } 624 625 void HttpStreamParser::CalculateResponseBodySize() { 626 // Figure how to determine EOF: 627 628 // For certain responses, we know the content length is always 0. From 629 // RFC 2616 Section 4.3 Message Body: 630 // 631 // For response messages, whether or not a message-body is included with 632 // a message is dependent on both the request method and the response 633 // status code (section 6.1.1). All responses to the HEAD request method 634 // MUST NOT include a message-body, even though the presence of entity- 635 // header fields might lead one to believe they do. All 1xx 636 // (informational), 204 (no content), and 304 (not modified) responses 637 // MUST NOT include a message-body. All other responses do include a 638 // message-body, although it MAY be of zero length. 639 switch (response_->headers->response_code()) { 640 // Note that 1xx was already handled earlier. 641 case 204: // No Content 642 case 205: // Reset Content 643 case 304: // Not Modified 644 response_body_length_ = 0; 645 break; 646 } 647 if (request_->method == "HEAD") 648 response_body_length_ = 0; 649 650 if (response_body_length_ == -1) { 651 // Ignore spurious chunked responses from HTTP/1.0 servers and 652 // proxies. Otherwise "Transfer-Encoding: chunked" trumps 653 // "Content-Length: N" 654 if (response_->headers->GetHttpVersion() >= HttpVersion(1, 1) && 655 response_->headers->HasHeaderValue("Transfer-Encoding", "chunked")) { 656 chunked_decoder_.reset(new HttpChunkedDecoder()); 657 } else { 658 response_body_length_ = response_->headers->GetContentLength(); 659 // If response_body_length_ is still -1, then we have to wait 660 // for the server to close the connection. 661 } 662 } 663 } 664 665 uint64 HttpStreamParser::GetUploadProgress() const { 666 if (!request_body_.get()) 667 return 0; 668 669 return request_body_->position(); 670 } 671 672 HttpResponseInfo* HttpStreamParser::GetResponseInfo() { 673 return response_; 674 } 675 676 bool HttpStreamParser::IsResponseBodyComplete() const { 677 if (chunked_decoder_.get()) 678 return chunked_decoder_->reached_eof(); 679 if (response_body_length_ != -1) 680 return response_body_read_ >= response_body_length_; 681 682 return false; // Must read to EOF. 683 } 684 685 bool HttpStreamParser::CanFindEndOfResponse() const { 686 return chunked_decoder_.get() || response_body_length_ >= 0; 687 } 688 689 bool HttpStreamParser::IsMoreDataBuffered() const { 690 return read_buf_->offset() > read_buf_unused_offset_; 691 } 692 693 bool HttpStreamParser::IsConnectionReused() const { 694 ClientSocketHandle::SocketReuseType reuse_type = connection_->reuse_type(); 695 return connection_->is_reused() || 696 reuse_type == ClientSocketHandle::UNUSED_IDLE; 697 } 698 699 void HttpStreamParser::SetConnectionReused() { 700 connection_->set_is_reused(true); 701 } 702 703 bool HttpStreamParser::IsConnectionReusable() const { 704 return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); 705 } 706 707 void HttpStreamParser::GetSSLInfo(SSLInfo* ssl_info) { 708 if (request_->url.SchemeIs("https") && connection_->socket()) { 709 SSLClientSocket* ssl_socket = 710 static_cast<SSLClientSocket*>(connection_->socket()); 711 ssl_socket->GetSSLInfo(ssl_info); 712 } 713 } 714 715 void HttpStreamParser::GetSSLCertRequestInfo( 716 SSLCertRequestInfo* cert_request_info) { 717 if (request_->url.SchemeIs("https") && connection_->socket()) { 718 SSLClientSocket* ssl_socket = 719 static_cast<SSLClientSocket*>(connection_->socket()); 720 ssl_socket->GetSSLCertRequestInfo(cert_request_info); 721 } 722 } 723 724 } // namespace net 725