| 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/spdy/spdy_http_stream.h" | 5 #include "net/spdy/spdy_http_stream.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <list> | 8 #include <list> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 namespace net { | 26 namespace net { |
| 27 | 27 |
| 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct) | 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct) |
| 29 : weak_factory_(this), | 29 : weak_factory_(this), |
| 30 spdy_session_(spdy_session), | 30 spdy_session_(spdy_session), |
| 31 stream_closed_(false), | 31 stream_closed_(false), |
| 32 closed_stream_status_(ERR_FAILED), | 32 closed_stream_status_(ERR_FAILED), |
| 33 closed_stream_id_(0), | 33 closed_stream_id_(0), |
| 34 request_info_(NULL), | 34 request_info_(NULL), |
| 35 response_info_(NULL), | 35 response_info_(NULL), |
| 36 response_headers_received_(false), | 36 response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE), |
| 37 user_buffer_len_(0), | 37 user_buffer_len_(0), |
| 38 request_body_buf_size_(0), | 38 request_body_buf_size_(0), |
| 39 buffered_read_callback_pending_(false), | 39 buffered_read_callback_pending_(false), |
| 40 more_read_data_pending_(false), | 40 more_read_data_pending_(false), |
| 41 direct_(direct) { | 41 direct_(direct) { |
| 42 DCHECK(spdy_session_); | 42 DCHECK(spdy_session_); |
| 43 } | 43 } |
| 44 | 44 |
| 45 SpdyHttpStream::~SpdyHttpStream() { | 45 SpdyHttpStream::~SpdyHttpStream() { |
| 46 if (stream_.get()) { | 46 if (stream_.get()) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 } | 99 } |
| 100 | 100 |
| 101 int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { | 101 int SpdyHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { |
| 102 CHECK(!callback.is_null()); | 102 CHECK(!callback.is_null()); |
| 103 if (stream_closed_) | 103 if (stream_closed_) |
| 104 return closed_stream_status_; | 104 return closed_stream_status_; |
| 105 | 105 |
| 106 CHECK(stream_.get()); | 106 CHECK(stream_.get()); |
| 107 | 107 |
| 108 // Check if we already have the response headers. If so, return synchronously. | 108 // Check if we already have the response headers. If so, return synchronously. |
| 109 if(stream_->response_received()) { | 109 if (response_headers_status_ == RESPONSE_HEADERS_ARE_COMPLETE) { |
| 110 CHECK(stream_->is_idle()); | 110 CHECK(stream_->is_idle()); |
| 111 return OK; | 111 return OK; |
| 112 } | 112 } |
| 113 | 113 |
| 114 // Still waiting for the response, return IO_PENDING. | 114 // Still waiting for the response, return IO_PENDING. |
| 115 CHECK(callback_.is_null()); | 115 CHECK(callback_.is_null()); |
| 116 callback_ = callback; | 116 callback_ = callback; |
| 117 return ERR_IO_PENDING; | 117 return ERR_IO_PENDING; |
| 118 } | 118 } |
| 119 | 119 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 void SpdyHttpStream::OnRequestHeadersSent() { | 285 void SpdyHttpStream::OnRequestHeadersSent() { |
| 286 if (!callback_.is_null()) | 286 if (!callback_.is_null()) |
| 287 DoCallback(OK); | 287 DoCallback(OK); |
| 288 | 288 |
| 289 // TODO(akalin): Do this immediately after sending the request | 289 // TODO(akalin): Do this immediately after sending the request |
| 290 // headers. | 290 // headers. |
| 291 if (HasUploadData()) | 291 if (HasUploadData()) |
| 292 ReadAndSendRequestBodyData(); | 292 ReadAndSendRequestBodyData(); |
| 293 } | 293 } |
| 294 | 294 |
| 295 int SpdyHttpStream::OnResponseHeadersReceived(const SpdyHeaderBlock& response, | 295 SpdyResponseHeadersStatus SpdyHttpStream::OnResponseHeadersUpdated( |
| 296 base::Time response_time, | 296 const SpdyHeaderBlock& response_headers) { |
| 297 int status) { | 297 CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_INCOMPLETE); |
| 298 |
| 298 if (!response_info_) { | 299 if (!response_info_) { |
| 299 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); | 300 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
| 300 push_response_info_.reset(new HttpResponseInfo); | 301 push_response_info_.reset(new HttpResponseInfo); |
| 301 response_info_ = push_response_info_.get(); | 302 response_info_ = push_response_info_.get(); |
| 302 } | 303 } |
| 303 | 304 |
| 304 // If the response is already received, these headers are too late. | 305 if (!SpdyHeadersToHttpResponse( |
| 305 if (response_headers_received_) { | 306 response_headers, stream_->GetProtocolVersion(), response_info_)) { |
| 306 LOG(WARNING) << "SpdyHttpStream headers received after response started."; | 307 // We do not have complete headers yet. |
| 307 return OK; | 308 return RESPONSE_HEADERS_ARE_INCOMPLETE; |
| 308 } | 309 } |
| 309 | 310 |
| 310 // TODO(mbelshe): This is the time of all headers received, not just time | 311 response_info_->response_time = stream_->response_time(); |
| 311 // to first byte. | 312 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; |
| 312 response_info_->response_time = base::Time::Now(); | |
| 313 | |
| 314 if (!SpdyHeadersToHttpResponse(response, stream_->GetProtocolVersion(), | |
| 315 response_info_)) { | |
| 316 // We might not have complete headers yet. | |
| 317 return ERR_INCOMPLETE_SPDY_HEADERS; | |
| 318 } | |
| 319 | |
| 320 response_headers_received_ = true; | |
| 321 // Don't store the SSLInfo in the response here, HttpNetworkTransaction | 313 // Don't store the SSLInfo in the response here, HttpNetworkTransaction |
| 322 // will take care of that part. | 314 // will take care of that part. |
| 323 SSLInfo ssl_info; | 315 SSLInfo ssl_info; |
| 324 NextProto protocol_negotiated = kProtoUnknown; | 316 NextProto protocol_negotiated = kProtoUnknown; |
| 325 stream_->GetSSLInfo(&ssl_info, | 317 stream_->GetSSLInfo(&ssl_info, |
| 326 &response_info_->was_npn_negotiated, | 318 &response_info_->was_npn_negotiated, |
| 327 &protocol_negotiated); | 319 &protocol_negotiated); |
| 328 response_info_->npn_negotiated_protocol = | 320 response_info_->npn_negotiated_protocol = |
| 329 SSLClientSocket::NextProtoToString(protocol_negotiated); | 321 SSLClientSocket::NextProtoToString(protocol_negotiated); |
| 330 response_info_->request_time = stream_->GetRequestTime(); | 322 response_info_->request_time = stream_->GetRequestTime(); |
| 331 switch (spdy_session_->GetProtocolVersion()) { | 323 switch (spdy_session_->GetProtocolVersion()) { |
| 332 case SPDY2: | 324 case SPDY2: |
| 333 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY2; | 325 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY2; |
| 334 break; | 326 break; |
| 335 case SPDY3: | 327 case SPDY3: |
| 336 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; | 328 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY3; |
| 337 break; | 329 break; |
| 338 case SPDY4: | 330 case SPDY4: |
| 339 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; | 331 response_info_->connection_info = HttpResponseInfo::CONNECTION_INFO_SPDY4; |
| 340 break; | 332 break; |
| 341 default: | 333 default: |
| 342 NOTREACHED(); | 334 NOTREACHED(); |
| 343 } | 335 } |
| 344 response_info_->vary_data | 336 response_info_->vary_data |
| 345 .Init(*request_info_, *response_info_->headers.get()); | 337 .Init(*request_info_, *response_info_->headers.get()); |
| 346 // TODO(ahendrickson): This is recorded after the entire SYN_STREAM control | |
| 347 // frame has been received and processed. Move to framer? | |
| 348 response_info_->response_time = response_time; | |
| 349 | 338 |
| 350 if (!callback_.is_null()) | 339 if (!callback_.is_null()) |
| 351 DoCallback(status); | 340 DoCallback(OK); |
| 352 | 341 |
| 353 return status; | 342 return RESPONSE_HEADERS_ARE_COMPLETE; |
| 354 } | 343 } |
| 355 | 344 |
| 356 int SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { | 345 void SpdyHttpStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { |
| 357 // SpdyStream won't call us with data if the header block didn't contain a | 346 CHECK_EQ(response_headers_status_, RESPONSE_HEADERS_ARE_COMPLETE); |
| 358 // valid set of headers. So we don't expect to not have headers received | |
| 359 // here. | |
| 360 if (!response_headers_received_) | |
| 361 return ERR_INCOMPLETE_SPDY_HEADERS; | |
| 362 | 347 |
| 363 // Note that data may be received for a SpdyStream prior to the user calling | 348 // Note that data may be received for a SpdyStream prior to the user calling |
| 364 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often | 349 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often |
| 365 // happen for server initiated streams. | 350 // happen for server initiated streams. |
| 366 DCHECK(stream_.get()); | 351 DCHECK(stream_.get()); |
| 367 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); | 352 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); |
| 368 if (buffer) { | 353 if (buffer) { |
| 369 response_body_queue_.Enqueue(buffer.Pass()); | 354 response_body_queue_.Enqueue(buffer.Pass()); |
| 370 | 355 |
| 371 if (user_buffer_.get()) { | 356 if (user_buffer_.get()) { |
| 372 // Handing small chunks of data to the caller creates measurable overhead. | 357 // Handing small chunks of data to the caller creates measurable overhead. |
| 373 // We buffer data in short time-spans and send a single read notification. | 358 // We buffer data in short time-spans and send a single read notification. |
| 374 ScheduleBufferedReadCallback(); | 359 ScheduleBufferedReadCallback(); |
| 375 } | 360 } |
| 376 } | 361 } |
| 377 return OK; | |
| 378 } | 362 } |
| 379 | 363 |
| 380 void SpdyHttpStream::OnDataSent() { | 364 void SpdyHttpStream::OnDataSent() { |
| 381 request_body_buf_size_ = 0; | 365 request_body_buf_size_ = 0; |
| 382 ReadAndSendRequestBodyData(); | 366 ReadAndSendRequestBodyData(); |
| 383 } | 367 } |
| 384 | 368 |
| 385 void SpdyHttpStream::OnClose(int status) { | 369 void SpdyHttpStream::OnClose(int status) { |
| 386 if (stream_.get()) { | 370 if (stream_.get()) { |
| 387 stream_closed_ = true; | 371 stream_closed_ = true; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 bool SpdyHttpStream::IsSpdyHttpStream() const { | 524 bool SpdyHttpStream::IsSpdyHttpStream() const { |
| 541 return true; | 525 return true; |
| 542 } | 526 } |
| 543 | 527 |
| 544 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 528 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
| 545 Close(false); | 529 Close(false); |
| 546 delete this; | 530 delete this; |
| 547 } | 531 } |
| 548 | 532 |
| 549 } // namespace net | 533 } // namespace net |
| OLD | NEW |