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

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

Issue 6134003: Prototype of chunked transfer encoded POST. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "net/base/auth.h" 9 #include "net/base/auth.h"
10 #include "net/base/io_buffer.h" 10 #include "net/base/io_buffer.h"
(...skipping 25 matching lines...) Expand all
36 user_read_buf_(NULL), 36 user_read_buf_(NULL),
37 user_read_buf_len_(0), 37 user_read_buf_len_(0),
38 user_callback_(NULL), 38 user_callback_(NULL),
39 connection_(connection), 39 connection_(connection),
40 net_log_(net_log), 40 net_log_(net_log),
41 ALLOW_THIS_IN_INITIALIZER_LIST( 41 ALLOW_THIS_IN_INITIALIZER_LIST(
42 io_callback_(this, &HttpStreamParser::OnIOComplete)) { 42 io_callback_(this, &HttpStreamParser::OnIOComplete)) {
43 DCHECK_EQ(0, read_buffer->offset()); 43 DCHECK_EQ(0, read_buffer->offset());
44 } 44 }
45 45
46 HttpStreamParser::~HttpStreamParser() {} 46 HttpStreamParser::~HttpStreamParser() {
47 if (request_body_ != NULL && request_body_->is_chunked())
48 request_body_->set_chunk_callback(NULL);
49 }
47 50
48 int HttpStreamParser::SendRequest(const std::string& request_line, 51 int HttpStreamParser::SendRequest(const std::string& request_line,
49 const HttpRequestHeaders& headers, 52 const HttpRequestHeaders& headers,
50 UploadDataStream* request_body, 53 UploadDataStream* request_body,
51 HttpResponseInfo* response, 54 HttpResponseInfo* response,
52 CompletionCallback* callback) { 55 CompletionCallback* callback) {
53 DCHECK_EQ(STATE_NONE, io_state_); 56 DCHECK_EQ(STATE_NONE, io_state_);
54 DCHECK(!user_callback_); 57 DCHECK(!user_callback_);
55 DCHECK(callback); 58 DCHECK(callback);
56 DCHECK(response); 59 DCHECK(response);
57 60
58 if (net_log_.IsLoggingAllEvents()) { 61 if (net_log_.IsLoggingAllEvents()) {
59 net_log_.AddEvent( 62 net_log_.AddEvent(
60 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 63 NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
61 make_scoped_refptr(new NetLogHttpRequestParameter( 64 make_scoped_refptr(new NetLogHttpRequestParameter(
62 request_line, headers))); 65 request_line, headers)));
63 } 66 }
64 response_ = response; 67 response_ = response;
65 std::string request = request_line + headers.ToString(); 68 std::string request = request_line + headers.ToString();
66 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request)); 69 scoped_refptr<StringIOBuffer> headers_io_buf(new StringIOBuffer(request));
67 request_headers_ = new DrainableIOBuffer(headers_io_buf, 70 request_headers_ = new DrainableIOBuffer(headers_io_buf,
68 headers_io_buf->size()); 71 headers_io_buf->size());
69 request_body_.reset(request_body); 72 request_body_.reset(request_body);
73 if (request_body_ != NULL && request_body_->is_chunked())
74 request_body_->set_chunk_callback(this);
70 75
71 io_state_ = STATE_SENDING_HEADERS; 76 io_state_ = STATE_SENDING_HEADERS;
72 int result = DoLoop(OK); 77 int result = DoLoop(OK);
73 if (result == ERR_IO_PENDING) 78 if (result == ERR_IO_PENDING)
74 user_callback_ = callback; 79 user_callback_ = callback;
75 80
76 return result > 0 ? OK : result; 81 return result > 0 ? OK : result;
77 } 82 }
78 83
79 int HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) { 84 int HttpStreamParser::ReadResponseHeaders(CompletionCallback* callback) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 141
137 // The client callback can do anything, including destroying this class, 142 // The client callback can do anything, including destroying this class,
138 // so any pending callback must be issued after everything else is done. 143 // so any pending callback must be issued after everything else is done.
139 if (result != ERR_IO_PENDING && user_callback_) { 144 if (result != ERR_IO_PENDING && user_callback_) {
140 CompletionCallback* c = user_callback_; 145 CompletionCallback* c = user_callback_;
141 user_callback_ = NULL; 146 user_callback_ = NULL;
142 c->Run(result); 147 c->Run(result);
143 } 148 }
144 } 149 }
145 150
151 void HttpStreamParser::OnChunkAvailable() {
152 // This method may get called while sending the headers or body, so check
153 // before processing the new data. If we were still initializing or sending
154 // headers, we will automatically start reading the chunks once we get into
155 // STATE_SENDING_BODY so nothing to do here.
156 DCHECK(io_state_ == STATE_SENDING_HEADERS || io_state_ == STATE_SENDING_BODY);
157 if (io_state_ == STATE_SENDING_BODY)
158 OnIOComplete(0);
159 }
160
146 int HttpStreamParser::DoLoop(int result) { 161 int HttpStreamParser::DoLoop(int result) {
147 bool can_do_more = true; 162 bool can_do_more = true;
148 do { 163 do {
149 switch (io_state_) { 164 switch (io_state_) {
150 case STATE_SENDING_HEADERS: 165 case STATE_SENDING_HEADERS:
151 if (result < 0) 166 if (result < 0)
152 can_do_more = false; 167 can_do_more = false;
153 else 168 else
154 result = DoSendHeaders(result); 169 result = DoSendHeaders(result);
155 break; 170 break;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 int bytes_remaining = request_headers_->BytesRemaining(); 216 int bytes_remaining = request_headers_->BytesRemaining();
202 if (bytes_remaining > 0) { 217 if (bytes_remaining > 0) {
203 // Record our best estimate of the 'request time' as the time when we send 218 // Record our best estimate of the 'request time' as the time when we send
204 // out the first bytes of the request headers. 219 // out the first bytes of the request headers.
205 if (bytes_remaining == request_headers_->size()) { 220 if (bytes_remaining == request_headers_->size()) {
206 response_->request_time = base::Time::Now(); 221 response_->request_time = base::Time::Now();
207 222
208 // We'll record the count of uncoalesced packets IFF coalescing will help, 223 // We'll record the count of uncoalesced packets IFF coalescing will help,
209 // and otherwise we'll use an enum to tell why it won't help. 224 // and otherwise we'll use an enum to tell why it won't help.
210 enum COALESCE_POTENTIAL { 225 enum COALESCE_POTENTIAL {
211 NO_ADVANTAGE = 0, // Coalescing won't reduce packet count. 226 // Coalescing won't reduce packet count.
212 HEADER_ONLY = 1, // There is only a header packet (can't coalesce). 227 NO_ADVANTAGE = 0,
213 COALESCE_POTENTIAL_MAX = 30 // Various cases of coalasced savings. 228 // There is only a header packet or we have a request body but the
229 // request body isn't available yet (can't coalesce).
230 HEADER_ONLY = 1,
231 // Various cases of coalasced savings.
232 COALESCE_POTENTIAL_MAX = 30
214 }; 233 };
215 size_t coalesce = HEADER_ONLY; 234 size_t coalesce = HEADER_ONLY;
216 if (request_body_ != NULL) { 235 if (request_body_ != NULL && !request_body_->is_chunked()) {
217 const size_t kBytesPerPacket = 1430; 236 const size_t kBytesPerPacket = 1430;
218 uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) / 237 uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) /
219 kBytesPerPacket; 238 kBytesPerPacket;
220 uint64 header_packets = (bytes_remaining + kBytesPerPacket - 1) / 239 uint64 header_packets = (bytes_remaining + kBytesPerPacket - 1) /
221 kBytesPerPacket; 240 kBytesPerPacket;
222 uint64 coalesced_packets = (request_body_->size() + bytes_remaining + 241 uint64 coalesced_packets = (request_body_->size() + bytes_remaining +
223 kBytesPerPacket - 1) / kBytesPerPacket; 242 kBytesPerPacket - 1) / kBytesPerPacket;
224 if (coalesced_packets < header_packets + body_packets) { 243 if (coalesced_packets < header_packets + body_packets) {
225 if (coalesced_packets > COALESCE_POTENTIAL_MAX) 244 if (coalesced_packets > COALESCE_POTENTIAL_MAX)
226 coalesce = COALESCE_POTENTIAL_MAX; 245 coalesce = COALESCE_POTENTIAL_MAX;
227 else 246 else
228 coalesce = static_cast<size_t>(header_packets + body_packets); 247 coalesce = static_cast<size_t>(header_packets + body_packets);
229 } else { 248 } else {
230 coalesce = NO_ADVANTAGE; 249 coalesce = NO_ADVANTAGE;
231 } 250 }
232 } 251 }
233 UMA_HISTOGRAM_ENUMERATION("Net.CoalescePotential", coalesce, 252 UMA_HISTOGRAM_ENUMERATION("Net.CoalescePotential", coalesce,
234 COALESCE_POTENTIAL_MAX); 253 COALESCE_POTENTIAL_MAX);
235 } 254 }
236 result = connection_->socket()->Write(request_headers_, 255 result = connection_->socket()->Write(request_headers_,
237 bytes_remaining, 256 bytes_remaining,
238 &io_callback_); 257 &io_callback_);
239 } else if (request_body_ != NULL && request_body_->size()) { 258 } else if (request_body_ != NULL &&
259 (request_body_->is_chunked() || request_body_->size())) {
240 io_state_ = STATE_SENDING_BODY; 260 io_state_ = STATE_SENDING_BODY;
241 result = OK; 261 result = OK;
242 } else { 262 } else {
243 io_state_ = STATE_REQUEST_SENT; 263 io_state_ = STATE_REQUEST_SENT;
244 } 264 }
245 return result; 265 return result;
246 } 266 }
247 267
248 int HttpStreamParser::DoSendBody(int result) { 268 int HttpStreamParser::DoSendBody(int result) {
249 if (result > 0) 269 request_body_->MarkConsumedAndFillBuffer(result);
250 request_body_->DidConsume(result);
251 270
252 if (!request_body_->eof()) { 271 if (!request_body_->eof()) {
253 int buf_len = static_cast<int>(request_body_->buf_len()); 272 int buf_len = static_cast<int>(request_body_->buf_len());
254 result = connection_->socket()->Write(request_body_->buf(), buf_len, 273 if (buf_len) {
255 &io_callback_); 274 result = connection_->socket()->Write(request_body_->buf(), buf_len,
275 &io_callback_);
276 } else {
277 // More POST data is to come hence wait for the callback.
278 result = ERR_IO_PENDING;
279 }
256 } else { 280 } else {
257 io_state_ = STATE_REQUEST_SENT; 281 io_state_ = STATE_REQUEST_SENT;
258 } 282 }
259 return result; 283 return result;
260 } 284 }
261 285
262 int HttpStreamParser::DoReadHeaders() { 286 int HttpStreamParser::DoReadHeaders() {
263 io_state_ = STATE_READ_HEADERS_COMPLETE; 287 io_state_ = STATE_READ_HEADERS_COMPLETE;
264 288
265 // Grow the read buffer if necessary. 289 // Grow the read buffer if necessary.
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 void HttpStreamParser::GetSSLCertRequestInfo( 654 void HttpStreamParser::GetSSLCertRequestInfo(
631 SSLCertRequestInfo* cert_request_info) { 655 SSLCertRequestInfo* cert_request_info) {
632 if (request_->url.SchemeIs("https") && connection_->socket()) { 656 if (request_->url.SchemeIs("https") && connection_->socket()) {
633 SSLClientSocket* ssl_socket = 657 SSLClientSocket* ssl_socket =
634 static_cast<SSLClientSocket*>(connection_->socket()); 658 static_cast<SSLClientSocket*>(connection_->socket());
635 ssl_socket->GetSSLCertRequestInfo(cert_request_info); 659 ssl_socket->GetSSLCertRequestInfo(cert_request_info);
636 } 660 }
637 } 661 }
638 662
639 } // namespace net 663 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698