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/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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |