spdy_http_stream.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_http_stream.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <list> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/load_flags.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_util.h" 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/http/http_request_headers.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_info.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_response_info.h" 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_util.h" 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_http_utils.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_session.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool direct) 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_factory_(this)), 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_(NULL), 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick spdy_session_(spdy_session), 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_info_(NULL), 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_finished_(false), 31201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_headers_received_(false), 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_(NULL), 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_len_(0), 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffered_read_callback_pending_(false), 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick more_read_data_pending_(false), 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick direct_(direct) { } 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) { 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen stream_ = spdy_stream; 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen stream_->SetDelegate(this); 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen response_headers_received_ = true; 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyHttpStream::~SpdyHttpStream() { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_) 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_->DetachDelegate(); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const BoundNetLog& stream_net_log, 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CompletionCallback* callback) { 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(!stream_.get()); 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (spdy_session_->IsClosed()) 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_CONNECTION_CLOSED; 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_info_ = request_info; 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (request_info_->method == "GET") { 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int error = spdy_session_->GetPushStream(request_info_->url, &stream_, 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_net_log); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error != OK) 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return error; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_.get()) 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return spdy_session_->CreateStream(request_info_->url, 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->priority, &stream_, 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_net_log, callback); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst HttpResponseInfo* SpdyHttpStream::GetResponseInfo() const { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response_info_; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochuint64 SpdyHttpStream::GetUploadProgress() const { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request_body_stream_.get()) 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return request_body_stream_->position(); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::ReadResponseHeaders(CompletionCallback* callback) { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(callback); 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(!stream_->cancelled()); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (stream_->closed()) 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->response_status(); 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check if we already have the response headers. If so, return synchronously. 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if(stream_->response_received()) { 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(stream_->is_idle()); 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return OK; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Still waiting for the response, return IO_PENDING. 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(!user_callback_); 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_callback_ = callback; 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_IO_PENDING; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::ReadResponseBody( 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IOBuffer* buf, int buf_len, CompletionCallback* callback) { 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(stream_->is_idle()); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(buf); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(buf_len); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(callback); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we have data buffered, complete the IO immediately. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_body_.empty()) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_read = 0; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!response_body_.empty() && buf_len > 0) { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<IOBufferWithSize> data = response_body_.front(); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int bytes_to_copy = std::min(buf_len, data->size()); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buf_len -= bytes_to_copy; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_to_copy == data->size()) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_body_.pop_front(); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int bytes_remaining = data->size() - bytes_to_copy; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_remaining); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_body_.pop_front(); 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch response_body_.push_front(make_scoped_refptr(new_buffer)); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_read += bytes_to_copy; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (SpdySession::flow_control()) 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->IncreaseRecvWindowSize(bytes_read); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bytes_read; 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (stream_->closed()) { 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->response_status(); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!user_callback_); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!user_buffer_); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_EQ(0, user_buffer_len_); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = callback; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_ = buf; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_len_ = buf_len; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_IO_PENDING; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SpdyHttpStream::Close(bool not_reusable) { 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Note: the not_reusable flag has no meaning for SPDY streams. 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Cancel(); 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenHttpStream* SpdyHttpStream::RenewStreamForAuth() { 15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::IsResponseBodyComplete() const { 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!stream_) 15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return stream_->closed(); 16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::CanFindEndOfResponse() const { 16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::IsMoreDataBuffered() const { 16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::IsConnectionReused() const { 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return spdy_session_->IsReused(); 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SpdyHttpStream::SetConnectionReused() { 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // SPDY doesn't need an indicator here. 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UploadDataStream* request_body, 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpResponseInfo* response, 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* callback) { 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time request_time = base::Time::Now(); 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(stream_.get()); 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->SetDelegate(this); 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick headers.get(), direct_); 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->set_spdy_headers(headers); 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->SetRequestTime(request_time); 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This should only get called in the case of a request occurring 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // during server push that has already begun but hasn't finished, 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // so we set the response's request time to be the actual one 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (response_info_) 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick response_info_->request_time = request_time; 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(!request_body_stream_.get()); 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (request_body) { 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (request_body->size()) 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_body_stream_.reset(request_body); 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick else 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete request_body; 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(callback); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!stream_->cancelled()); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(response); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!stream_->pushed() && stream_->closed()) { 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_->response_status() == OK) 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_FAILED; 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->response_status(); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SendRequest can be called in two cases. 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a) A client initiated request. In this case, |response_info_| should be 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NULL to start with. 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // b) A client request which matches a response that the server has already 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // pushed. 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (push_response_info_.get()) { 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *response = *(push_response_info_.get()); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch push_response_info_.reset(); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick else 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(static_cast<HttpResponseInfo*>(NULL), response_info_); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_info_ = response; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_upload_data = request_body_stream_.get() != NULL; 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int result = stream_->SendRequest(has_upload_data); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result == ERR_IO_PENDING) { 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!user_callback_); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = callback; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::Cancel() { 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_session_) 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_session_->CancelPendingCreateStreams(&stream_); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = NULL; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_) 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_->Cancel(); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::OnSendHeadersComplete(int status) { 2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (user_callback_) 2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DoCallback(status); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return request_body_stream_.get() == NULL; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::OnSendBody() { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(request_body_stream_.get()); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len = static_cast<int>(request_body_stream_->buf_len()); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!buf_len) 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->WriteStreamData(request_body_stream_->buf(), buf_len, 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy::DATA_FLAG_FIN); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::OnSendBodyComplete(int status) { 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(request_body_stream_.get()); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_body_stream_->DidConsume(status); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return request_body_stream_->eof(); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response, 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time response_time, 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int status) { 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_info_) { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(stream_->pushed()); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch push_response_info_.reset(new HttpResponseInfo); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_info_ = push_response_info_.get(); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If the response is already received, these headers are too late. 281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (response_headers_received_) { 282201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(WARNING) << "SpdyHttpStream headers received after response started."; 283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return OK; 284201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 285201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(mbelshe): This is the time of all headers received, not just time 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // to first byte. 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick response_info_->response_time = base::Time::Now(); 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!SpdyHeadersToHttpResponse(response, response_info_)) { 291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // We might not have complete headers yet. 292201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return ERR_INCOMPLETE_SPDY_HEADERS; 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_headers_received_ = true; 29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Don't store the SSLInfo in the response here, HttpNetworkTransaction 29721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // will take care of that part. 29821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SSLInfo ssl_info; 29921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen stream_->GetSSLInfo(&ssl_info, 300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &response_info_->was_npn_negotiated); 301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_info_->request_time = stream_->GetRequestTime(); 302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_info_->vary_data.Init(*request_info_, *response_info_->headers); 303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TODO(ahendrickson): This is recorded after the entire SYN_STREAM control 304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // frame has been received and processed. Move to framer? 305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_info_->response_time = response_time; 306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_callback_) 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(status); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return status; 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::OnDataReceived(const char* data, int length) { 313201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // SpdyStream won't call us with data if the header block didn't contain a 314201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // valid set of headers. So we don't expect to not have headers received 315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // here. 316201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK(response_headers_received_); 317201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that data may be received for a SpdyStream prior to the user calling 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // happen for server initiated streams. 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!stream_->closed() || stream_->pushed()); 3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (length > 0) { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the received data. 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IOBufferWithSize* io_buffer = new IOBufferWithSize(length); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(io_buffer->data(), data, length); 326513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch response_body_.push_back(make_scoped_refptr(io_buffer)); 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_buffer_) { 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Handing small chunks of data to the caller creates measurable overhead. 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We buffer data in short time-spans and send a single read notification. 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleBufferedReadCallback(); 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::OnDataSent(int length) { 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For HTTP streams, no data is sent from the client while in the OPEN state, 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so it is never called. 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::OnClose(int status) { 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool invoked_callback = false; 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (status == net::OK) { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to complete any pending buffered read now. 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch invoked_callback = DoBufferedReadCallback(); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!invoked_callback && user_callback_) 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(status); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::ScheduleBufferedReadCallback() { 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there is already a scheduled DoBufferedReadCallback, don't issue 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // another one. Mark that we have received more data and return. 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (buffered_read_callback_pending_) { 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch more_read_data_pending_ = true; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch more_read_data_pending_ = false; 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffered_read_callback_pending_ = true; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int kBufferTimeMs = 1; 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, read_callback_factory_. 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(&SpdyHttpStream::DoBufferedReadCallback), 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBufferTimeMs); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Checks to see if we should wait for more buffered data before notifying 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the caller. Returns true if we should wait, false otherwise. 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::ShouldWaitForMoreBufferedData() const { 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the response is complete, there is no point in waiting. 3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (stream_->closed()) 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_buffered = 0; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::list<scoped_refptr<IOBufferWithSize> >::const_iterator it; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (it = response_body_.begin(); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != response_body_.end() && bytes_buffered < user_buffer_len_; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it) 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_buffered += (*it)->size(); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bytes_buffered < user_buffer_len_; 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::DoBufferedReadCallback() { 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch read_callback_factory_.RevokeAll(); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffered_read_callback_pending_ = false; 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the transaction is cancelled or errored out, we don't need to complete 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the read. 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!stream_ || stream_->response_status() != OK || stream_->cancelled()) 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When more_read_data_pending_ is true, it means that more data has 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // arrived since we started waiting. Wait a little longer and continue 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to buffer. 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (more_read_data_pending_ && ShouldWaitForMoreBufferedData()) { 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleBufferedReadCallback(); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = 0; 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_buffer_) { 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = ReadResponseBody(user_buffer_, user_buffer_len_, user_callback_); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_NE(rv, ERR_IO_PENDING); 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_ = NULL; 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_len_ = 0; 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(rv); 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::DoCallback(int rv) { 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_NE(rv, ERR_IO_PENDING); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(user_callback_); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since Run may result in being called back, clear user_callback_ in advance. 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* c = user_callback_; 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = NULL; 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch c->Run(rv); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SpdyHttpStream::GetSSLInfo(SSLInfo* ssl_info) { 4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(stream_); 4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool using_npn; 4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->GetSSLInfo(ssl_info, &using_npn); 4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SpdyHttpStream::GetSSLCertRequestInfo( 4313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SSLCertRequestInfo* cert_request_info) { 4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(stream_); 4333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->GetSSLCertRequestInfo(cert_request_info); 4343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 437