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

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

Issue 9293029: net: Introduce SeekableIOBuffer and clean up HttpStreamParser. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix comments Created 8 years, 10 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
« no previous file with comments | « net/http/http_stream_parser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/string_util.h" 9 #include "base/string_util.h"
10 #include "net/base/address_list.h" 10 #include "net/base/address_list.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 if (count_same_value || field_value != field_value2) 55 if (count_same_value || field_value != field_value2)
56 return true; 56 return true;
57 } 57 }
58 return false; 58 return false;
59 } 59 }
60 60
61 } // namespace 61 } // namespace
62 62
63 namespace net { 63 namespace net {
64 64
65 // Similar to DrainableIOBuffer(), but this version comes with its own
66 // storage. The motivation is to avoid repeated allocations of
67 // DrainableIOBuffer.
68 //
69 // Example:
70 //
71 // scoped_refptr<SeekableIOBuffer> buf = new SeekableIOBuffer(1024);
72 // // capacity() == 1024. size() == BytesRemaining == BytesConsumed() == 0.
73 // // data() points to the beginning of the buffer.
74 //
75 // // Read() takes an IOBuffer.
76 // int bytes_read = some_reader->Read(buf, buf->capacity());
77 // buf->DidAppend(bytes_read);
78 // // size() == BytesRemaining() == bytes_read. data() is unaffected.
79 //
80 // while (buf->BytesRemaining() > 0) {
81 // // Write() takes an IOBuffer. If it takes const char*, we could
82 /// // simply use the regular IOBuffer like buf->data() + offset.
83 // int bytes_written = Write(buf, buf->BytesRemaining());
84 // buf->DidConsume(bytes_written);
85 // }
86 // // BytesRemaining() == 0. BytesConsumed() == size().
87 // // data() points to the end of the comsumed bytes (exclusive).
88 //
89 // // If you want to reuse the buffer, be sure to clear the buffer.
90 // buf->Clear();
91 // // size() == BytesRemaining() == BytesConsumed() == 0.
92 // // data() points to the beginning of the buffer.
93 //
94 class HttpStreamParser::SeekableIOBuffer : public net::IOBuffer {
95 public:
96 explicit SeekableIOBuffer(int capacity)
97 : IOBuffer(capacity),
98 real_data_(data_),
99 capacity_(capacity),
100 size_(0),
101 used_(0) {
102 }
103
104 // DidConsume() changes the |data_| pointer so that |data_| always points
105 // to the first unconsumed byte.
106 void DidConsume(int bytes) {
107 SetOffset(used_ + bytes);
108 }
109
110 // Returns the number of unconsumed bytes.
111 int BytesRemaining() const {
112 return size_ - used_;
113 }
114
115 // Seeks to an arbitrary point in the buffer. The notion of bytes consumed
116 // and remaining are updated appropriately.
117 void SetOffset(int bytes) {
118 DCHECK_GE(bytes, 0);
119 DCHECK_LE(bytes, size_);
120 used_ = bytes;
121 data_ = real_data_ + used_;
122 }
123
124 // Called after data is added to the buffer. Adds |bytes| added to
125 // |size_|. data() is unaffected.
126 void DidAppend(int bytes) {
127 DCHECK_GE(bytes, 0);
128 DCHECK_GE(size_ + bytes, 0);
129 DCHECK_LE(size_ + bytes, capacity_);
130 size_ += bytes;
131 }
132
133 // Changes the logical size to 0, and the offset to 0.
134 void Clear() {
135 size_ = 0;
136 SetOffset(0);
137 }
138
139 // Returns the logical size of the buffer (i.e the number of bytes of data
140 // in the buffer).
141 int size() const { return size_; }
142
143 // Returns the capacity of the buffer. The capacity is the size used when
144 // the object is created.
145 int capacity() const { return capacity_; };
146
147 private:
148 virtual ~SeekableIOBuffer() {
149 // data_ will be deleted in IOBuffer::~IOBuffer().
150 data_ = real_data_;
151 }
152
153 char* real_data_;
154 int capacity_;
155 int size_;
156 int used_;
157 };
158
65 // 2 CRLFs + max of 8 hex chars. 159 // 2 CRLFs + max of 8 hex chars.
66 const size_t HttpStreamParser::kChunkHeaderFooterSize = 12; 160 const size_t HttpStreamParser::kChunkHeaderFooterSize = 12;
67 161
68 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, 162 HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
69 const HttpRequestInfo* request, 163 const HttpRequestInfo* request,
70 GrowableIOBuffer* read_buffer, 164 GrowableIOBuffer* read_buffer,
71 const BoundNetLog& net_log) 165 const BoundNetLog& net_log)
72 : io_state_(STATE_NONE), 166 : io_state_(STATE_NONE),
73 request_(request), 167 request_(request),
74 request_headers_(NULL), 168 request_headers_(NULL),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 AddressList address; 215 AddressList address;
122 int result = connection_->socket()->GetPeerAddress(&address); 216 int result = connection_->socket()->GetPeerAddress(&address);
123 if (result != OK) 217 if (result != OK)
124 return result; 218 return result;
125 response_->socket_address = HostPortPair::FromAddrInfo(address.head()); 219 response_->socket_address = HostPortPair::FromAddrInfo(address.head());
126 220
127 std::string request = request_line + headers.ToString(); 221 std::string request = request_line + headers.ToString();
128 request_body_.reset(request_body); 222 request_body_.reset(request_body);
129 if (request_body_ != NULL && request_body_->is_chunked()) { 223 if (request_body_ != NULL && request_body_->is_chunked()) {
130 request_body_->set_chunk_callback(this); 224 request_body_->set_chunk_callback(this);
131 // The raw chunk buffer is guaranteed to be large enough to hold the 225 // The chunk buffer is guaranteed to be large enough to hold the encoded
132 // encoded chunk. 226 // chunk.
133 raw_chunk_buf_ = new IOBufferWithSize(UploadDataStream::GetBufferSize() + 227 chunk_buf_ = new SeekableIOBuffer(UploadDataStream::GetBufferSize() +
134 kChunkHeaderFooterSize); 228 kChunkHeaderFooterSize);
135 } 229 }
136 230
137 io_state_ = STATE_SENDING_HEADERS; 231 io_state_ = STATE_SENDING_HEADERS;
138 232
139 // If we have a small request body, then we'll merge with the headers into a 233 // If we have a small request body, then we'll merge with the headers into a
140 // single write. 234 // single write.
141 bool did_merge = false; 235 bool did_merge = false;
142 if (ShouldMergeRequestHeadersAndBody(request, request_body_.get())) { 236 if (ShouldMergeRequestHeadersAndBody(request, request_body_.get())) {
143 size_t merged_size = request.size() + request_body->size(); 237 size_t merged_size = request.size() + request_body->size();
144 scoped_refptr<IOBuffer> merged_request_headers_and_body( 238 scoped_refptr<IOBuffer> merged_request_headers_and_body(
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 io_state_ = STATE_REQUEST_SENT; 436 io_state_ = STATE_REQUEST_SENT;
343 } 437 }
344 return result; 438 return result;
345 } 439 }
346 440
347 int HttpStreamParser::DoSendChunkedBody(int result) { 441 int HttpStreamParser::DoSendChunkedBody(int result) {
348 // |result| is the number of bytes sent from the last call to 442 // |result| is the number of bytes sent from the last call to
349 // DoSendChunkedBody(), or 0 (i.e. OK) the first time. 443 // DoSendChunkedBody(), or 0 (i.e. OK) the first time.
350 444
351 // Send the remaining data in the chunk buffer. 445 // Send the remaining data in the chunk buffer.
352 if (chunk_buf_.get()) { 446 chunk_buf_->DidConsume(result);
353 chunk_buf_->DidConsume(result); 447 if (chunk_buf_->BytesRemaining() > 0) {
354 if (chunk_buf_->BytesRemaining() > 0) { 448 return connection_->socket()->Write(chunk_buf_,
355 return connection_->socket()->Write(chunk_buf_, 449 chunk_buf_->BytesRemaining(),
356 chunk_buf_->BytesRemaining(), 450 io_callback_);
357 io_callback_);
358 }
359 } 451 }
360 452
361 if (sent_last_chunk_) { 453 if (sent_last_chunk_) {
362 io_state_ = STATE_REQUEST_SENT; 454 io_state_ = STATE_REQUEST_SENT;
363 return OK; 455 return OK;
364 } 456 }
365 457
366 // |chunk_length_without_encoding_| is 0 when DoSendBody() is first 458 // |chunk_length_without_encoding_| is 0 when DoSendBody() is first
367 // called, hence the first call to MarkConsumedAndFillBuffer() is a noop. 459 // called, hence the first call to MarkConsumedAndFillBuffer() is a noop.
368 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_); 460 request_body_->MarkConsumedAndFillBuffer(chunk_length_without_encoding_);
369 chunk_length_without_encoding_ = 0; 461 chunk_length_without_encoding_ = 0;
370 462
371 if (request_body_->eof()) { 463 if (request_body_->eof()) {
464 chunk_buf_->Clear();
372 const int chunk_length = EncodeChunk( 465 const int chunk_length = EncodeChunk(
373 base::StringPiece(), raw_chunk_buf_->data(), raw_chunk_buf_->size()); 466 base::StringPiece(), chunk_buf_->data(), chunk_buf_->capacity());
374 chunk_buf_ = new DrainableIOBuffer(raw_chunk_buf_, chunk_length); 467 chunk_buf_->DidAppend(chunk_length);
375 sent_last_chunk_ = true; 468 sent_last_chunk_ = true;
376 } else if (request_body_->buf_len() > 0) { 469 } else if (request_body_->buf_len() > 0) {
377 // Encode and send the buffer as 1 chunk. 470 // Encode and send the buffer as 1 chunk.
378 const base::StringPiece payload(request_body_->buf()->data(), 471 const base::StringPiece payload(request_body_->buf()->data(),
379 request_body_->buf_len()); 472 request_body_->buf_len());
473 chunk_buf_->Clear();
380 const int chunk_length = EncodeChunk( 474 const int chunk_length = EncodeChunk(
381 payload, raw_chunk_buf_->data(), raw_chunk_buf_->size()); 475 payload, chunk_buf_->data(), chunk_buf_->capacity());
382 chunk_buf_ = new DrainableIOBuffer(raw_chunk_buf_, chunk_length); 476 chunk_buf_->DidAppend(chunk_length);
383 chunk_length_without_encoding_ = payload.size(); 477 chunk_length_without_encoding_ = payload.size();
384 } else { 478 } else {
385 // Nothing to send. More POST data is yet to come? 479 // Nothing to send. More POST data is yet to come?
386 return ERR_IO_PENDING; 480 return ERR_IO_PENDING;
387 } 481 }
388 482
389 return connection_->socket()->Write(chunk_buf_, chunk_buf_->BytesRemaining(), 483 return connection_->socket()->Write(chunk_buf_, chunk_buf_->BytesRemaining(),
390 io_callback_); 484 io_callback_);
391 } 485 }
392 486
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 request_body->IsInMemory() && 917 request_body->IsInMemory() &&
824 request_body->size() > 0) { 918 request_body->size() > 0) {
825 size_t merged_size = request_headers.size() + request_body->size(); 919 size_t merged_size = request_headers.size() + request_body->size();
826 if (merged_size <= kMaxMergedHeaderAndBodySize) 920 if (merged_size <= kMaxMergedHeaderAndBodySize)
827 return true; 921 return true;
828 } 922 }
829 return false; 923 return false;
830 } 924 }
831 925
832 } // namespace net 926 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_stream_parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698