Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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" | 9 #include "base/stringprintf.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 if (count_same_value || field_value != field_value2) | 54 if (count_same_value || field_value != field_value2) |
| 55 return true; | 55 return true; |
| 56 } | 56 } |
| 57 return false; | 57 return false; |
| 58 } | 58 } |
| 59 | 59 |
| 60 } // namespace | 60 } // namespace |
| 61 | 61 |
| 62 namespace net { | 62 namespace net { |
| 63 | 63 |
| 64 // 2 CRLFs + max of 8 hex chars. | |
| 65 const int HttpStreamParser::kChunkHeaderFooterSize = 12; | |
| 66 | |
| 67 // The chunk buffer is guaranteed to be large enough to hold the encoded | |
| 68 // chunk. | |
|
wtc
2012/01/18 22:49:24
Add "The size of the chunk buffer (chunk_buf_)." a
satorux1
2012/01/18 23:42:30
Done.
| |
| 69 static const size_t kChunkBufferSize = | |
| 70 net::UploadDataStream::kBufferSize + | |
|
wtc
2012/01/18 22:49:24
The net:: prefix is not necessary because this is
satorux1
2012/01/18 23:42:30
Done.
| |
| 71 HttpStreamParser::kChunkHeaderFooterSize; | |
| 72 | |
| 64 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, | 73 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, |
| 65 const HttpRequestInfo* request, | 74 const HttpRequestInfo* request, |
| 66 GrowableIOBuffer* read_buffer, | 75 GrowableIOBuffer* read_buffer, |
| 67 const BoundNetLog& net_log) | 76 const BoundNetLog& net_log) |
| 68 : io_state_(STATE_NONE), | 77 : io_state_(STATE_NONE), |
| 69 request_(request), | 78 request_(request), |
| 70 request_headers_(NULL), | 79 request_headers_(NULL), |
| 71 request_body_(NULL), | 80 request_body_(NULL), |
| 72 read_buf_(read_buffer), | 81 read_buf_(read_buffer), |
| 73 read_buf_unused_offset_(0), | 82 read_buf_unused_offset_(0), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 return result; | 130 return result; |
| 122 response_->socket_address = HostPortPair::FromAddrInfo(address.head()); | 131 response_->socket_address = HostPortPair::FromAddrInfo(address.head()); |
| 123 | 132 |
| 124 std::string request = request_line + headers.ToString(); | 133 std::string request = request_line + headers.ToString(); |
| 125 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); | 134 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); |
| 126 request_headers_ = new DrainableIOBuffer(headers_io_buf, | 135 request_headers_ = new DrainableIOBuffer(headers_io_buf, |
| 127 headers_io_buf->size()); | 136 headers_io_buf->size()); |
| 128 request_body_.reset(request_body); | 137 request_body_.reset(request_body); |
| 129 if (request_body_ != NULL && request_body_->is_chunked()) { | 138 if (request_body_ != NULL && request_body_->is_chunked()) { |
| 130 request_body_->set_chunk_callback(this); | 139 request_body_->set_chunk_callback(this); |
| 131 const int kChunkHeaderFooterSize = 12; // 2 CRLFs + max of 8 hex chars. | 140 chunk_buf_ = new IOBuffer(kChunkBufferSize); |
| 132 chunk_buf_ = new IOBuffer(request_body_->GetMaxBufferSize() + | |
|
wtc
2012/01/18 22:49:24
I understand why we need kChunkBufferSize. The al
satorux1
2012/01/18 23:42:30
I thought about keeping GetMaxBufferSize() but cha
| |
| 133 kChunkHeaderFooterSize); | |
| 134 } | 141 } |
| 135 | 142 |
| 136 io_state_ = STATE_SENDING_HEADERS; | 143 io_state_ = STATE_SENDING_HEADERS; |
| 137 result = DoLoop(OK); | 144 result = DoLoop(OK); |
| 138 if (result == ERR_IO_PENDING) | 145 if (result == ERR_IO_PENDING) |
| 139 callback_ = callback; | 146 callback_ = callback; |
| 140 | 147 |
| 141 return result > 0 ? OK : result; | 148 return result > 0 ? OK : result; |
| 142 } | 149 } |
| 143 | 150 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 346 io_state_ = STATE_REQUEST_SENT; | 353 io_state_ = STATE_REQUEST_SENT; |
| 347 return OK; | 354 return OK; |
| 348 } | 355 } |
| 349 | 356 |
| 350 // |chunk_length_without_encoding_| is 0 when DoSendBody() is first | 357 // |chunk_length_without_encoding_| is 0 when DoSendBody() is first |
| 351 // called, hence the first call to MarkConsumedAndFillBuffer() is a noop. | 358 // called, hence the first call to MarkConsumedAndFillBuffer() is a noop. |
| 352 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); | 359 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); |
| 353 chunk_length_without_encoding_ = 0; | 360 chunk_length_without_encoding_ = 0; |
| 354 chunk_length_ = 0; | 361 chunk_length_ = 0; |
| 355 | 362 |
| 356 int buf_len = static_cast<int>(request_body_->buf_len()); | |
| 357 if (request_body_->eof()) { | 363 if (request_body_->eof()) { |
| 358 static const char kLastChunk[] = "0\r\n\r\n"; | 364 EncodeChunk("", chunk_buf_->data(), kChunkBufferSize); |
|
wtc
2012/01/18 22:55:00
Nit: it may be cheaper to construct an empty Strin
satorux1
2012/01/18 23:42:30
Done.
| |
| 359 chunk_length_ = strlen(kLastChunk); | |
| 360 memcpy(chunk_buf_->data(), kLastChunk, chunk_length_); | |
| 361 sent_last_chunk_ = true; | 365 sent_last_chunk_ = true; |
| 362 } else if (buf_len) { | 366 } else if (request_body_->buf_len() > 0) { |
| 363 // Encode and send the buffer as 1 chunk. | 367 // Encode and send the buffer as 1 chunk. |
| 364 std::string chunk_header = StringPrintf("%X\r\n", buf_len); | 368 const base::StringPiece payload(request_body_->buf()->data(), |
| 365 char* chunk_ptr = chunk_buf_->data(); | 369 request_body_->buf_len()); |
| 366 memcpy(chunk_ptr, chunk_header.data(), chunk_header.length()); | 370 chunk_length_ = EncodeChunk(payload, chunk_buf_->data(), |
| 367 chunk_ptr += chunk_header.length(); | 371 kChunkBufferSize); |
| 368 memcpy(chunk_ptr, request_body_->buf()->data(), buf_len); | 372 chunk_length_without_encoding_ = payload.size(); |
| 369 chunk_ptr += buf_len; | |
| 370 memcpy(chunk_ptr, "\r\n", 2); | |
| 371 chunk_length_without_encoding_ = buf_len; | |
| 372 chunk_length_ = chunk_header.length() + buf_len + 2; | |
| 373 } | 373 } |
| 374 | 374 |
| 375 if (!chunk_length_) // chunk_buf_ is empty. More POST data is yet to come? | 375 if (!chunk_length_) // chunk_buf_ is empty. More POST data is yet to come? |
| 376 return ERR_IO_PENDING; | 376 return ERR_IO_PENDING; |
| 377 | 377 |
| 378 return connection_->socket()->Write(chunk_buf_, chunk_length_, | 378 return connection_->socket()->Write(chunk_buf_, chunk_length_, |
| 379 io_callback_); | 379 io_callback_); |
| 380 } | 380 } |
| 381 | 381 |
| 382 // Non-chunked request body. | 382 // Non-chunked request body. |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 770 | 770 |
| 771 void HttpStreamParser::GetSSLCertRequestInfo( | 771 void HttpStreamParser::GetSSLCertRequestInfo( |
| 772 SSLCertRequestInfo* cert_request_info) { | 772 SSLCertRequestInfo* cert_request_info) { |
| 773 if (request_->url.SchemeIs("https") && connection_->socket()) { | 773 if (request_->url.SchemeIs("https") && connection_->socket()) { |
| 774 SSLClientSocket* ssl_socket = | 774 SSLClientSocket* ssl_socket = |
| 775 static_cast<SSLClientSocket*>(connection_->socket()); | 775 static_cast<SSLClientSocket*>(connection_->socket()); |
| 776 ssl_socket->GetSSLCertRequestInfo(cert_request_info); | 776 ssl_socket->GetSSLCertRequestInfo(cert_request_info); |
| 777 } | 777 } |
| 778 } | 778 } |
| 779 | 779 |
| 780 int HttpStreamParser::EncodeChunk(const base::StringPiece& payload, | |
| 781 char* output, | |
| 782 size_t output_size) { | |
| 783 if (output_size < payload.size() + kChunkHeaderFooterSize) | |
| 784 return -1; | |
| 785 | |
| 786 char* cursor = output; | |
| 787 // Add the header. | |
| 788 std::string chunk_header = | |
| 789 StringPrintf("%X\r\n", static_cast<int>(payload.size())); | |
| 790 memcpy(cursor, chunk_header.data(), chunk_header.length()); | |
| 791 cursor += chunk_header.length(); | |
|
wtc
2012/01/18 22:49:24
If the standard C library function snprintf() is n
satorux1
2012/01/18 23:42:30
My understanding is that use of snprintf here shou
| |
| 792 // Add the payload. | |
| 793 memcpy(cursor, payload.data(), payload.size()); | |
| 794 cursor += payload.size(); | |
|
wtc
2012/01/18 22:55:00
I wonder if we should check for the last-chunk cas
satorux1
2012/01/18 23:42:30
Done. if payload is empty, the last chunk is essen
| |
| 795 // Add the trailing CRLF. | |
| 796 memcpy(cursor, "\r\n", 2); | |
| 797 cursor += 2; | |
| 798 | |
| 799 return cursor - output; | |
| 800 } | |
| 801 | |
| 780 } // namespace net | 802 } // namespace net |
| OLD | NEW |