| 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 12 matching lines...) Expand all Loading... |
| 23 #include "net/spdy/spdy_protocol.h" | 23 #include "net/spdy/spdy_protocol.h" |
| 24 #include "net/spdy/spdy_session.h" | 24 #include "net/spdy/spdy_session.h" |
| 25 | 25 |
| 26 namespace net { | 26 namespace net { |
| 27 | 27 |
| 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, | 28 SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, |
| 29 bool direct) | 29 bool direct) |
| 30 : weak_factory_(this), | 30 : weak_factory_(this), |
| 31 spdy_session_(spdy_session), | 31 spdy_session_(spdy_session), |
| 32 stream_closed_(false), | 32 stream_closed_(false), |
| 33 closed_stream_pushed_(false), | |
| 34 closed_stream_status_(ERR_FAILED), | 33 closed_stream_status_(ERR_FAILED), |
| 35 closed_stream_id_(0), | 34 closed_stream_id_(0), |
| 36 request_info_(NULL), | 35 request_info_(NULL), |
| 37 has_upload_data_(false), | 36 has_upload_data_(false), |
| 38 response_info_(NULL), | 37 response_info_(NULL), |
| 39 response_headers_received_(false), | 38 response_headers_received_(false), |
| 40 user_buffer_len_(0), | 39 user_buffer_len_(0), |
| 41 raw_request_body_buf_size_(0), | 40 raw_request_body_buf_size_(0), |
| 42 buffered_read_callback_pending_(false), | 41 buffered_read_callback_pending_(false), |
| 43 more_read_data_pending_(false), | 42 more_read_data_pending_(false), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 67 | 66 |
| 68 request_info_ = request_info; | 67 request_info_ = request_info; |
| 69 if (request_info_->method == "GET") { | 68 if (request_info_->method == "GET") { |
| 70 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, | 69 int error = spdy_session_->GetPushStream(request_info_->url, &stream_, |
| 71 stream_net_log); | 70 stream_net_log); |
| 72 if (error != OK) | 71 if (error != OK) |
| 73 return error; | 72 return error; |
| 74 | 73 |
| 75 // |stream_| may be NULL even if OK was returned. | 74 // |stream_| may be NULL even if OK was returned. |
| 76 if (stream_) { | 75 if (stream_) { |
| 76 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
| 77 stream_->SetDelegate(this); | 77 stream_->SetDelegate(this); |
| 78 return OK; | 78 return OK; |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 | 81 |
| 82 int rv = stream_request_.StartRequest( | 82 int rv = stream_request_.StartRequest( |
| 83 spdy_session_, request_info_->url, priority, | 83 SPDY_REQUEST_RESPONSE_STREAM, spdy_session_, request_info_->url, |
| 84 stream_net_log, | 84 priority, stream_net_log, |
| 85 base::Bind(&SpdyHttpStream::OnStreamCreated, | 85 base::Bind(&SpdyHttpStream::OnStreamCreated, |
| 86 weak_factory_.GetWeakPtr(), callback)); | 86 weak_factory_.GetWeakPtr(), callback)); |
| 87 | 87 |
| 88 if (rv == OK) { | 88 if (rv == OK) { |
| 89 stream_ = stream_request_.ReleaseStream(); | 89 stream_ = stream_request_.ReleaseStream(); |
| 90 stream_->SetDelegate(this); | 90 stream_->SetDelegate(this); |
| 91 } | 91 } |
| 92 | 92 |
| 93 return rv; | 93 return rv; |
| 94 } | 94 } |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 if (stream_id == 0) | 196 if (stream_id == 0) |
| 197 return false; | 197 return false; |
| 198 | 198 |
| 199 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); | 199 return spdy_session_->GetLoadTimingInfo(stream_id, load_timing_info); |
| 200 } | 200 } |
| 201 | 201 |
| 202 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, | 202 int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, |
| 203 HttpResponseInfo* response, | 203 HttpResponseInfo* response, |
| 204 const CompletionCallback& callback) { | 204 const CompletionCallback& callback) { |
| 205 if (stream_closed_) { | 205 if (stream_closed_) { |
| 206 if (stream_->pushed()) | 206 if (stream_->type() == SPDY_PUSH_STREAM) |
| 207 return closed_stream_status_; | 207 return closed_stream_status_; |
| 208 | 208 |
| 209 return (closed_stream_status_ == OK) ? ERR_FAILED : closed_stream_status_; | 209 return (closed_stream_status_ == OK) ? ERR_FAILED : closed_stream_status_; |
| 210 } | 210 } |
| 211 | 211 |
| 212 base::Time request_time = base::Time::Now(); | 212 base::Time request_time = base::Time::Now(); |
| 213 CHECK(stream_.get()); | 213 CHECK(stream_.get()); |
| 214 | 214 |
| 215 stream_->SetRequestTime(request_time); | 215 stream_->SetRequestTime(request_time); |
| 216 // This should only get called in the case of a request occurring | 216 // This should only get called in the case of a request occurring |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 | 249 |
| 250 response_info_ = response; | 250 response_info_ = response; |
| 251 | 251 |
| 252 // Put the peer's IP address and port into the response. | 252 // Put the peer's IP address and port into the response. |
| 253 IPEndPoint address; | 253 IPEndPoint address; |
| 254 int result = stream_->GetPeerAddress(&address); | 254 int result = stream_->GetPeerAddress(&address); |
| 255 if (result != OK) | 255 if (result != OK) |
| 256 return result; | 256 return result; |
| 257 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); | 257 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); |
| 258 | 258 |
| 259 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); | 259 if (stream_->type() == SPDY_PUSH_STREAM) { |
| 260 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, | 260 // Pushed streams do not send any data, and should always be |
| 261 headers.get(), stream_->GetProtocolVersion(), | 261 // idle. However, we still want to return ERR_IO_PENDING to mimic |
| 262 direct_); | 262 // non-push behavior. The callback will be called when the |
| 263 stream_->net_log().AddEvent( | 263 // response is received. |
| 264 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, | 264 result = ERR_IO_PENDING; |
| 265 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); | 265 } else { |
| 266 result = | 266 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 267 stream_->SendRequestHeaders( | 267 CreateSpdyHeadersFromHttpRequest( |
| 268 headers.Pass(), | 268 *request_info_, request_headers, |
| 269 has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); | 269 headers.get(), stream_->GetProtocolVersion(), |
| 270 direct_); |
| 271 stream_->net_log().AddEvent( |
| 272 NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, |
| 273 base::Bind(&SpdyHeaderBlockNetLogCallback, headers.get())); |
| 274 result = |
| 275 stream_->SendRequestHeaders( |
| 276 headers.Pass(), |
| 277 has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND); |
| 278 } |
| 279 |
| 270 if (result == ERR_IO_PENDING) { | 280 if (result == ERR_IO_PENDING) { |
| 271 CHECK(callback_.is_null()); | 281 CHECK(callback_.is_null()); |
| 272 callback_ = callback; | 282 callback_ = callback; |
| 273 } | 283 } |
| 274 return result; | 284 return result; |
| 275 } | 285 } |
| 276 | 286 |
| 277 void SpdyHttpStream::Cancel() { | 287 void SpdyHttpStream::Cancel() { |
| 278 callback_.Reset(); | 288 callback_.Reset(); |
| 279 if (stream_) { | 289 if (stream_) { |
| 280 stream_->Cancel(); | 290 stream_->Cancel(); |
| 281 DCHECK(!stream_); | 291 DCHECK(!stream_); |
| 282 } | 292 } |
| 283 } | 293 } |
| 284 | 294 |
| 285 SpdySendStatus SpdyHttpStream::OnSendRequestHeadersComplete() { | 295 void SpdyHttpStream::OnSendRequestHeadersComplete() { |
| 286 if (!callback_.is_null()) | 296 if (!callback_.is_null()) |
| 287 DoCallback(OK); | 297 DoCallback(OK); |
| 288 return has_upload_data_ ? MORE_DATA_TO_SEND : NO_MORE_DATA_TO_SEND; | |
| 289 } | 298 } |
| 290 | 299 |
| 291 void SpdyHttpStream::OnSendBody() { | 300 void SpdyHttpStream::OnSendBody() { |
| 292 CHECK(request_info_ && request_info_->upload_data_stream); | 301 CHECK(request_info_ && request_info_->upload_data_stream); |
| 293 if (raw_request_body_buf_size_ > 0) { | 302 if (raw_request_body_buf_size_ > 0) { |
| 294 SendRequestBodyData(); | 303 SendRequestBodyData(); |
| 295 } else { | 304 } else { |
| 296 // We shouldn't be called if there's no more data to read. | 305 // We shouldn't be called if there's no more data to read. |
| 297 CHECK(!request_info_->upload_data_stream->IsEOF()); | 306 CHECK(!request_info_->upload_data_stream->IsEOF()); |
| 298 ReadAndSendRequestBodyData(); | 307 ReadAndSendRequestBodyData(); |
| 299 } | 308 } |
| 300 } | 309 } |
| 301 | 310 |
| 302 void SpdyHttpStream::OnSendBodyComplete() { | 311 void SpdyHttpStream::OnSendBodyComplete() { |
| 303 // |status| is the number of bytes written to the SPDY stream. | 312 // |status| is the number of bytes written to the SPDY stream. |
| 304 CHECK(request_info_ && request_info_->upload_data_stream); | 313 CHECK(request_info_ && request_info_->upload_data_stream); |
| 305 raw_request_body_buf_size_ = 0; | 314 raw_request_body_buf_size_ = 0; |
| 306 } | 315 } |
| 307 | 316 |
| 308 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response, | 317 int SpdyHttpStream::OnResponseReceived(const SpdyHeaderBlock& response, |
| 309 base::Time response_time, | 318 base::Time response_time, |
| 310 int status) { | 319 int status) { |
| 311 if (!response_info_) { | 320 if (!response_info_) { |
| 312 DCHECK(stream_->pushed()); | 321 DCHECK_EQ(stream_->type(), SPDY_PUSH_STREAM); |
| 313 push_response_info_.reset(new HttpResponseInfo); | 322 push_response_info_.reset(new HttpResponseInfo); |
| 314 response_info_ = push_response_info_.get(); | 323 response_info_ = push_response_info_.get(); |
| 315 } | 324 } |
| 316 | 325 |
| 317 // If the response is already received, these headers are too late. | 326 // If the response is already received, these headers are too late. |
| 318 if (response_headers_received_) { | 327 if (response_headers_received_) { |
| 319 LOG(WARNING) << "SpdyHttpStream headers received after response started."; | 328 LOG(WARNING) << "SpdyHttpStream headers received after response started."; |
| 320 return OK; | 329 return OK; |
| 321 } | 330 } |
| 322 | 331 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 // SpdyStream won't call us with data if the header block didn't contain a | 378 // SpdyStream won't call us with data if the header block didn't contain a |
| 370 // valid set of headers. So we don't expect to not have headers received | 379 // valid set of headers. So we don't expect to not have headers received |
| 371 // here. | 380 // here. |
| 372 if (!response_headers_received_) | 381 if (!response_headers_received_) |
| 373 return ERR_INCOMPLETE_SPDY_HEADERS; | 382 return ERR_INCOMPLETE_SPDY_HEADERS; |
| 374 | 383 |
| 375 // Note that data may be received for a SpdyStream prior to the user calling | 384 // Note that data may be received for a SpdyStream prior to the user calling |
| 376 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often | 385 // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often |
| 377 // happen for server initiated streams. | 386 // happen for server initiated streams. |
| 378 DCHECK(stream_.get()); | 387 DCHECK(stream_.get()); |
| 379 DCHECK(!stream_->closed() || stream_->pushed()); | 388 DCHECK(!stream_->closed() || stream_->type() == SPDY_PUSH_STREAM); |
| 380 if (buffer) { | 389 if (buffer) { |
| 381 response_body_queue_.Enqueue(buffer.Pass()); | 390 response_body_queue_.Enqueue(buffer.Pass()); |
| 382 | 391 |
| 383 if (user_buffer_) { | 392 if (user_buffer_) { |
| 384 // Handing small chunks of data to the caller creates measurable overhead. | 393 // Handing small chunks of data to the caller creates measurable overhead. |
| 385 // We buffer data in short time-spans and send a single read notification. | 394 // We buffer data in short time-spans and send a single read notification. |
| 386 ScheduleBufferedReadCallback(); | 395 ScheduleBufferedReadCallback(); |
| 387 } | 396 } |
| 388 } | 397 } |
| 389 return OK; | 398 return OK; |
| 390 } | 399 } |
| 391 | 400 |
| 392 void SpdyHttpStream::OnDataSent() { | 401 void SpdyHttpStream::OnDataSent() { |
| 393 // For HTTP streams, no data is sent from the client while in the OPEN state, | 402 // For HTTP streams, no data is sent from the client while in the OPEN state, |
| 394 // so it is never called. | 403 // so it is never called. |
| 395 CHECK(false); | 404 CHECK(false); |
| 396 } | 405 } |
| 397 | 406 |
| 398 void SpdyHttpStream::OnClose(int status) { | 407 void SpdyHttpStream::OnClose(int status) { |
| 399 if (stream_) { | 408 if (stream_) { |
| 400 stream_closed_ = true; | 409 stream_closed_ = true; |
| 401 closed_stream_pushed_ = stream_->pushed(); | |
| 402 closed_stream_status_ = status; | 410 closed_stream_status_ = status; |
| 403 closed_stream_id_ = stream_->stream_id(); | 411 closed_stream_id_ = stream_->stream_id(); |
| 404 } | 412 } |
| 405 stream_.reset(); | 413 stream_.reset(); |
| 406 bool invoked_callback = false; | 414 bool invoked_callback = false; |
| 407 if (status == net::OK) { | 415 if (status == net::OK) { |
| 408 // We need to complete any pending buffered read now. | 416 // We need to complete any pending buffered read now. |
| 409 invoked_callback = DoBufferedReadCallback(); | 417 invoked_callback = DoBufferedReadCallback(); |
| 410 } | 418 } |
| 411 if (!invoked_callback && !callback_.is_null()) | 419 if (!invoked_callback && !callback_.is_null()) |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 bool SpdyHttpStream::IsSpdyHttpStream() const { | 555 bool SpdyHttpStream::IsSpdyHttpStream() const { |
| 548 return true; | 556 return true; |
| 549 } | 557 } |
| 550 | 558 |
| 551 void SpdyHttpStream::Drain(HttpNetworkSession* session) { | 559 void SpdyHttpStream::Drain(HttpNetworkSession* session) { |
| 552 Close(false); | 560 Close(false); |
| 553 delete this; | 561 delete this; |
| 554 } | 562 } |
| 555 | 563 |
| 556 } // namespace net | 564 } // namespace net |
| OLD | NEW |