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