1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/address_list.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/host_port_pair.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/load_flags.h" 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_util.h" 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "net/http/http_request_headers.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_info.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_response_info.h" 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_util.h" 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_http_utils.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_session.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen bool direct) 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_factory_(this)), 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_(NULL), 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick spdy_session_(spdy_session), 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_info_(NULL), 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_finished_(false), 33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_headers_received_(false), 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_(NULL), 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_len_(0), 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffered_read_callback_pending_(false), 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick more_read_data_pending_(false), 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick direct_(direct) { } 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) { 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen stream_ = spdy_stream; 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen stream_->SetDelegate(this); 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen response_headers_received_ = true; 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyHttpStream::~SpdyHttpStream() { 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_) 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_->DetachDelegate(); 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint SpdyHttpStream::InitializeStream(const HttpRequestInfo* request_info, 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const BoundNetLog& stream_net_log, 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CompletionCallback* callback) { 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(!stream_.get()); 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (spdy_session_->IsClosed()) 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_CONNECTION_CLOSED; 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch request_info_ = request_info; 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (request_info_->method == "GET") { 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int error = spdy_session_->GetPushStream(request_info_->url, &stream_, 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_net_log); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (error != OK) 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return error; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_.get()) 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return spdy_session_->CreateStream(request_info_->url, 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->priority, &stream_, 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_net_log, callback); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst HttpResponseInfo* SpdyHttpStream::GetResponseInfo() const { 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return response_info_; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochuint64 SpdyHttpStream::GetUploadProgress() const { 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!request_body_stream_.get()) 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return request_body_stream_->position(); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::ReadResponseHeaders(CompletionCallback* callback) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(callback); 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(!stream_->cancelled()); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (stream_->closed()) 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->response_status(); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check if we already have the response headers. If so, return synchronously. 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if(stream_->response_received()) { 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(stream_->is_idle()); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return OK; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Still waiting for the response, return IO_PENDING. 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(!user_callback_); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_callback_ = callback; 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ERR_IO_PENDING; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::ReadResponseBody( 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IOBuffer* buf, int buf_len, CompletionCallback* callback) { 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(stream_->is_idle()); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(buf); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(buf_len); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(callback); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we have data buffered, complete the IO immediately. 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_body_.empty()) { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_read = 0; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!response_body_.empty() && buf_len > 0) { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<IOBufferWithSize> data = response_body_.front(); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int bytes_to_copy = std::min(buf_len, data->size()); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buf_len -= bytes_to_copy; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_to_copy == data->size()) { 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_body_.pop_front(); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int bytes_remaining = data->size() - bytes_to_copy; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_remaining); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_body_.pop_front(); 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch response_body_.push_front(make_scoped_refptr(new_buffer)); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_read += bytes_to_copy; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (SpdySession::flow_control()) 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->IncreaseRecvWindowSize(bytes_read); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bytes_read; 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (stream_->closed()) { 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->response_status(); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!user_callback_); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!user_buffer_); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_EQ(0, user_buffer_len_); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = callback; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_ = buf; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_len_ = buf_len; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_IO_PENDING; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SpdyHttpStream::Close(bool not_reusable) { 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Note: the not_reusable flag has no meaning for SPDY streams. 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Cancel(); 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenHttpStream* SpdyHttpStream::RenewStreamForAuth() { 15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::IsResponseBodyComplete() const { 15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!stream_) 16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return stream_->closed(); 16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::CanFindEndOfResponse() const { 16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::IsMoreDataBuffered() const { 16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SpdyHttpStream::IsConnectionReused() const { 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return spdy_session_->IsReused(); 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SpdyHttpStream::SetConnectionReused() { 17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // SPDY doesn't need an indicator here. 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SpdyHttpStream::IsConnectionReusable() const { 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // SPDY streams aren't considered reusable. 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdyHttpStream::set_chunk_callback(ChunkCallback* callback) { 186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (request_body_stream_ != NULL) 187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_body_stream_->set_chunk_callback(callback); 188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers, 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UploadDataStream* request_body, 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HttpResponseInfo* response, 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* callback) { 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time request_time = base::Time::Now(); 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(stream_.get()); 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->SetDelegate(this); 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock); 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, 201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick headers.get(), direct_); 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->set_spdy_headers(headers); 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->SetRequestTime(request_time); 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This should only get called in the case of a request occurring 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // during server push that has already begun but hasn't finished, 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // so we set the response's request time to be the actual one 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (response_info_) 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick response_info_->request_time = request_time; 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CHECK(!request_body_stream_.get()); 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (request_body) { 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (request_body->size() || request_body->is_chunked()) 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_body_stream_.reset(request_body); 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick else 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete request_body; 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(callback); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!stream_->cancelled()); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(response); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!stream_->pushed() && stream_->closed()) { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_->response_status() == OK) 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_FAILED; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_->response_status(); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SendRequest can be called in two cases. 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a) A client initiated request. In this case, |response_info_| should be 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NULL to start with. 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // b) A client request which matches a response that the server has already 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // pushed. 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (push_response_info_.get()) { 2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *response = *(push_response_info_.get()); 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch push_response_info_.reset(); 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick else 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(static_cast<HttpResponseInfo*>(NULL), response_info_); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_info_ = response; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Put the peer's IP address and port into the response. 246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AddressList address; 247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int result = stream_->GetPeerAddress(&address); 248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (result != OK) 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return result; 250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen response_info_->socket_address = HostPortPair::FromAddrInfo(address.head()); 251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_upload_data = request_body_stream_.get() != NULL; 253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen result = stream_->SendRequest(has_upload_data); 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result == ERR_IO_PENDING) { 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(!user_callback_); 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = callback; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::Cancel() { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (spdy_session_) 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch spdy_session_->CancelPendingCreateStreams(&stream_); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = NULL; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stream_) 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_->Cancel(); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::OnSendHeadersComplete(int status) { 2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (user_callback_) 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DoCallback(status); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return request_body_stream_.get() == NULL; 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::OnSendBody() { 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(request_body_stream_.get()); 277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int buf_len = static_cast<int>(request_body_stream_->buf_len()); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!buf_len) 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool is_chunked = request_body_stream_->is_chunked(); 282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(satish): For non-chunked POST data, we set DATA_FLAG_FIN for all 283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // blocks of data written out. This is wrong if the POST data was larger than 284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // UploadDataStream::kBufSize as that is the largest buffer that 285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // UploadDataStream returns at a time and we'll be setting the FIN flag for 286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // each block of data written out. 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool eof = !is_chunked || request_body_stream_->IsOnLastChunk(); 288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return stream_->WriteStreamData( 289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_body_stream_->buf(), buf_len, 290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen eof ? spdy::DATA_FLAG_FIN : spdy::DATA_FLAG_NONE); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) { 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(request_body_stream_.get()); 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen request_body_stream_->MarkConsumedAndFillBuffer(status); 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen *eof = request_body_stream_->eof(); 298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!*eof && 299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_body_stream_->is_chunked() && 300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen !request_body_stream_->buf_len()) 301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return ERR_IO_PENDING; 302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return OK; 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SpdyHttpStream::OnResponseReceived(const spdy::SpdyHeaderBlock& response, 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time response_time, 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int status) { 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_info_) { 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(stream_->pushed()); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch push_response_info_.reset(new HttpResponseInfo); 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_info_ = push_response_info_.get(); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If the response is already received, these headers are too late. 316201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (response_headers_received_) { 317201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(WARNING) << "SpdyHttpStream headers received after response started."; 318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return OK; 319201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(mbelshe): This is the time of all headers received, not just time 3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // to first byte. 3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick response_info_->response_time = base::Time::Now(); 3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!SpdyHeadersToHttpResponse(response, response_info_)) { 326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // We might not have complete headers yet. 327201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return ERR_INCOMPLETE_SPDY_HEADERS; 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_headers_received_ = true; 33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Don't store the SSLInfo in the response here, HttpNetworkTransaction 33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // will take care of that part. 33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SSLInfo ssl_info; 33421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen stream_->GetSSLInfo(&ssl_info, 335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &response_info_->was_npn_negotiated); 336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_info_->request_time = stream_->GetRequestTime(); 337201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_info_->vary_data.Init(*request_info_, *response_info_->headers); 338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // TODO(ahendrickson): This is recorded after the entire SYN_STREAM control 339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // frame has been received and processed. Move to framer? 340201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch response_info_->response_time = response_time; 341201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_callback_) 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(status); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return status; 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::OnDataReceived(const char* data, int length) { 348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // SpdyStream won't call us with data if the header block didn't contain a 349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // valid set of headers. So we don't expect to not have headers received 350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // here. 351201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK(response_headers_received_); 352201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note that data may be received for a SpdyStream prior to the user calling 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ReadResponseBody(), therefore user_buffer_ may be NULL. This may often 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // happen for server initiated streams. 3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!stream_->closed() || stream_->pushed()); 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (length > 0) { 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the received data. 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IOBufferWithSize* io_buffer = new IOBufferWithSize(length); 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(io_buffer->data(), data, length); 361513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch response_body_.push_back(make_scoped_refptr(io_buffer)); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_buffer_) { 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Handing small chunks of data to the caller creates measurable overhead. 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We buffer data in short time-spans and send a single read notification. 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleBufferedReadCallback(); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::OnDataSent(int length) { 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For HTTP streams, no data is sent from the client while in the OPEN state, 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so it is never called. 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::OnClose(int status) { 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool invoked_callback = false; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (status == net::OK) { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to complete any pending buffered read now. 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch invoked_callback = DoBufferedReadCallback(); 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!invoked_callback && user_callback_) 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(status); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::ScheduleBufferedReadCallback() { 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there is already a scheduled DoBufferedReadCallback, don't issue 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // another one. Mark that we have received more data and return. 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (buffered_read_callback_pending_) { 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch more_read_data_pending_ = true; 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch more_read_data_pending_ = false; 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffered_read_callback_pending_ = true; 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int kBufferTimeMs = 1; 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, read_callback_factory_. 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(&SpdyHttpStream::DoBufferedReadCallback), 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kBufferTimeMs); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Checks to see if we should wait for more buffered data before notifying 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the caller. Returns true if we should wait, false otherwise. 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::ShouldWaitForMoreBufferedData() const { 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the response is complete, there is no point in waiting. 4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (stream_->closed()) 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int bytes_buffered = 0; 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::list<scoped_refptr<IOBufferWithSize> >::const_iterator it; 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (it = response_body_.begin(); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != response_body_.end() && bytes_buffered < user_buffer_len_; 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it) 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_buffered += (*it)->size(); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bytes_buffered < user_buffer_len_; 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyHttpStream::DoBufferedReadCallback() { 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch read_callback_factory_.RevokeAll(); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buffered_read_callback_pending_ = false; 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the transaction is cancelled or errored out, we don't need to complete 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the read. 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!stream_ || stream_->response_status() != OK || stream_->cancelled()) 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When more_read_data_pending_ is true, it means that more data has 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // arrived since we started waiting. Wait a little longer and continue 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to buffer. 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (more_read_data_pending_ && ShouldWaitForMoreBufferedData()) { 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleBufferedReadCallback(); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = 0; 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (user_buffer_) { 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = ReadResponseBody(user_buffer_, user_buffer_len_, user_callback_); 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_NE(rv, ERR_IO_PENDING); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_ = NULL; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_buffer_len_ = 0; 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoCallback(rv); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyHttpStream::DoCallback(int rv) { 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK_NE(rv, ERR_IO_PENDING); 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(user_callback_); 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since Run may result in being called back, clear user_callback_ in advance. 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompletionCallback* c = user_callback_; 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_ = NULL; 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch c->Run(rv); 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SpdyHttpStream::GetSSLInfo(SSLInfo* ssl_info) { 4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(stream_); 4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool using_npn; 4623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->GetSSLInfo(ssl_info, &using_npn); 4633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SpdyHttpStream::GetSSLCertRequestInfo( 4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SSLCertRequestInfo* cert_request_info) { 4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(stream_); 4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_->GetSSLCertRequestInfo(cert_request_info); 4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 471ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool SpdyHttpStream::IsSpdyHttpStream() const { 472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 476