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