| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "net/http/http_stream_parser.h" | 5 #include "net/http/http_stream_parser.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/stringprintf.h" | |
| 10 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 11 #include "net/base/address_list.h" | 10 #include "net/base/address_list.h" |
| 12 #include "net/base/auth.h" | 11 #include "net/base/auth.h" |
| 13 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
| 14 #include "net/base/ssl_cert_request_info.h" | 13 #include "net/base/ssl_cert_request_info.h" |
| 15 #include "net/http/http_net_log_params.h" | 14 #include "net/http/http_net_log_params.h" |
| 16 #include "net/http/http_request_headers.h" | 15 #include "net/http/http_request_headers.h" |
| 17 #include "net/http/http_request_info.h" | 16 #include "net/http/http_request_info.h" |
| 18 #include "net/http/http_response_headers.h" | 17 #include "net/http/http_response_headers.h" |
| 19 #include "net/http/http_util.h" | 18 #include "net/http/http_util.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 if (count_same_value || field_value != field_value2) | 53 if (count_same_value || field_value != field_value2) |
| 55 return true; | 54 return true; |
| 56 } | 55 } |
| 57 return false; | 56 return false; |
| 58 } | 57 } |
| 59 | 58 |
| 60 } // namespace | 59 } // namespace |
| 61 | 60 |
| 62 namespace net { | 61 namespace net { |
| 63 | 62 |
| 63 // 2 CRLFs + max of 8 hex chars. |
| 64 const size_t HttpStreamParser::kChunkHeaderFooterSize = 12; |
| 65 |
| 66 // The size of the chunk buffer (chunk_buf_). The chunk buffer is |
| 67 // guaranteed to be large enough to hold the encoded chunk. |
| 68 static const size_t kChunkBufferSize = |
| 69 UploadDataStream::kBufferSize + |
| 70 HttpStreamParser::kChunkHeaderFooterSize; |
| 71 |
| 64 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, | 72 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, |
| 65 const HttpRequestInfo* request, | 73 const HttpRequestInfo* request, |
| 66 GrowableIOBuffer* read_buffer, | 74 GrowableIOBuffer* read_buffer, |
| 67 const BoundNetLog& net_log) | 75 const BoundNetLog& net_log) |
| 68 : io_state_(STATE_NONE), | 76 : io_state_(STATE_NONE), |
| 69 request_(request), | 77 request_(request), |
| 70 request_headers_(NULL), | 78 request_headers_(NULL), |
| 71 request_body_(NULL), | 79 request_body_(NULL), |
| 72 read_buf_(read_buffer), | 80 read_buf_(read_buffer), |
| 73 read_buf_unused_offset_(0), | 81 read_buf_unused_offset_(0), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 return result; | 129 return result; |
| 122 response_->socket_address = HostPortPair::FromAddrInfo(address.head()); | 130 response_->socket_address = HostPortPair::FromAddrInfo(address.head()); |
| 123 | 131 |
| 124 std::string request = request_line + headers.ToString(); | 132 std::string request = request_line + headers.ToString(); |
| 125 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); | 133 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); |
| 126 request_headers_ = new DrainableIOBuffer(headers_io_buf, | 134 request_headers_ = new DrainableIOBuffer(headers_io_buf, |
| 127 headers_io_buf->size()); | 135 headers_io_buf->size()); |
| 128 request_body_.reset(request_body); | 136 request_body_.reset(request_body); |
| 129 if (request_body_ != NULL && request_body_->is_chunked()) { | 137 if (request_body_ != NULL && request_body_->is_chunked()) { |
| 130 request_body_->set_chunk_callback(this); | 138 request_body_->set_chunk_callback(this); |
| 131 const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. | 139 chunk_buf_ = new IOBuffer(kChunkBufferSize); |
| 132 chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + | |
| 133 kChunkHeaderFooterSize); | |
| 134 } | 140 } |
| 135 | 141 |
| 136 io_state_ = STATE_SENDING_HEADERS; | 142 io_state_ = STATE_SENDING_HEADERS; |
| 137 result = DoLoop(OK); | 143 result = DoLoop(OK); |
| 138 if (result == ERR_IO_PENDING) | 144 if (result == ERR_IO_PENDING) |
| 139 callback_ = callback; | 145 callback_ = callback; |
| 140 | 146 |
| 141 return result > 0 ? OK : result; | 147 return result > 0 ? OK : result; |
| 142 } | 148 } |
| 143 | 149 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 if (sent_last_chunk_) { | 348 if (sent_last_chunk_) { |
| 343 io_state_ = STATE_REQUEST_SENT; | 349 io_state_ = STATE_REQUEST_SENT; |
| 344 return OK; | 350 return OK; |
| 345 } | 351 } |
| 346 | 352 |
| 347 // |chunk_length_without_encoding_| is 0 when DoSendBody() is first | 353 // |chunk_length_without_encoding_| is 0 when DoSendBody() is first |
| 348 // called, hence the first call to MarkConsumedAndFillBuffer() is a noop. | 354 // called, hence the first call to MarkConsumedAndFillBuffer() is a noop. |
| 349 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); | 355 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); |
| 350 chunk_length_without_encoding_ = 0; | 356 chunk_length_without_encoding_ = 0; |
| 351 | 357 |
| 352 int buf_len = static_cast<int>(request_body_->buf_len()); | |
| 353 if (request_body_->eof()) { | 358 if (request_body_->eof()) { |
| 354 static const char kLastChunk[] = "0\r\n\r\n"; | 359 chunk_length_ = EncodeChunk( |
| 355 chunk_length_ = strlen(kLastChunk); | 360 base::StringPiece(), chunk_buf_->data(), kChunkBufferSize); |
| 356 memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); | |
| 357 sent_last_chunk_ = true; | 361 sent_last_chunk_ = true; |
| 358 } else if (buf_len) { | 362 } else if (request_body_->buf_len() > 0) { |
| 359 // Encode and send the buffer as 1 chunk. | 363 // Encode and send the buffer as 1 chunk. |
| 360 std::string chunk_header = StringPrintf("%X\r\n", buf_len); | 364 const base::StringPiece payload(request_body_->buf()->data(), |
| 361 char* chunk_ptr = chunk_buf_->data(); | 365 request_body_->buf_len()); |
| 362 memcpy(chunk_ptr, chunk_header.data(), chunk_header.length()); | 366 chunk_length_ = EncodeChunk(payload, chunk_buf_->data(), |
| 363 chunk_ptr += chunk_header.length(); | 367 kChunkBufferSize); |
| 364 memcpy(chunk_ptr, request_body_->buf()->data(), buf_len); | 368 chunk_length_without_encoding_ = payload.size(); |
| 365 chunk_ptr += buf_len; | |
| 366 memcpy(chunk_ptr, "\r\n", 2); | |
| 367 chunk_length_without_encoding_ = buf_len; | |
| 368 chunk_length_ = chunk_header.length() + buf_len + 2; | |
| 369 } else { | 369 } else { |
| 370 // Nothing to send. More POST data is yet to come? | 370 // Nothing to send. More POST data is yet to come? |
| 371 return ERR_IO_PENDING; | 371 return ERR_IO_PENDING; |
| 372 } | 372 } |
| 373 | 373 |
| 374 return connection_->socket()->Write(chunk_buf_, chunk_length_, | 374 return connection_->socket()->Write(chunk_buf_, chunk_length_, |
| 375 io_callback_); | 375 io_callback_); |
| 376 } | 376 } |
| 377 | 377 |
| 378 // Non-chunked request body. | 378 // Non-chunked request body. |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 | 766 |
| 767 void HttpStreamParser::GetSSLCertRequestInfo( | 767 void HttpStreamParser::GetSSLCertRequestInfo( |
| 768 SSLCertRequestInfo* cert_request_info) { | 768 SSLCertRequestInfo* cert_request_info) { |
| 769 if (request_->url.SchemeIs("https") && connection_->socket()) { | 769 if (request_->url.SchemeIs("https") && connection_->socket()) { |
| 770 SSLClientSocket* ssl_socket = | 770 SSLClientSocket* ssl_socket = |
| 771 static_cast<SSLClientSocket*>(connection_->socket()); | 771 static_cast<SSLClientSocket*>(connection_->socket()); |
| 772 ssl_socket->GetSSLCertRequestInfo(cert_request_info); | 772 ssl_socket->GetSSLCertRequestInfo(cert_request_info); |
| 773 } | 773 } |
| 774 } | 774 } |
| 775 | 775 |
| 776 int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, |
| 777 char* output, |
| 778 size_t output_size) { |
| 779 if (output_size < payload.size() + kChunkHeaderFooterSize) |
| 780 return ERR_INVALID_ARGUMENT; |
| 781 |
| 782 char* cursor = output; |
| 783 // Add the header. |
| 784 const int num_chars = base::snprintf(output, output_size, |
| 785 "%X\r\n", |
| 786 static_cast<int>(payload.size())); |
| 787 cursor += num_chars; |
| 788 // Add the payload if any. |
| 789 if (payload.size() > 0) { |
| 790 memcpy(cursor, payload.data(), payload.size()); |
| 791 cursor += payload.size(); |
| 792 } |
| 793 // Add the trailing CRLF. |
| 794 memcpy(cursor, "\r\n", 2); |
| 795 cursor += 2; |
| 796 |
| 797 return cursor - output; |
| 798 } |
| 799 |
| 776 } // namespace net | 800 } // namespace net |
| OLD | NEW |