Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(907)

Side by Side Diff: net/http/http_stream_parser.cc

Issue 9242018: Factor out chunk encoding logic into HttpStreamParser::EncodeChunk(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698