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