quic_http_stream.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_http_stream.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback_helpers.h" 85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_response_headers.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_client_session.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/quic/quic_http_utils.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_reliable_client_stream.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_utils.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/socket/next_proto.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_frame_builder.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_framer.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_http_utils.h" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/ssl/ssl_info.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const size_t kHeaderBufInitialSize = 4096; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)QuicHttpStream::QuicHttpStream(const base::WeakPtr<QuicClientSession> session) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : next_state_(STATE_NONE), 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session_(session), 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_(NULL), 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_info_(NULL), 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_(NULL), 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority_(MINIMUM_PRIORITY), 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_(NULL), 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_status_(OK), 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_headers_received_(false), 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) read_buf_(new GrowableIOBuffer()), 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_len_(0), 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(session_); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicHttpStream::~QuicHttpStream() { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(false); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestPriority priority, 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BoundNetLog& stream_net_log, 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(!stream_); 52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!session_) 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return ERR_CONNECTION_CLOSED; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_net_log_ = stream_net_log; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_info_ = request_info; 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority_ = priority; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int rv = stream_request_.StartRequest( 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session_, &stream_, base::Bind(&QuicHttpStream::OnStreamReady, 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) weak_factory_.GetWeakPtr())); 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (rv == ERR_IO_PENDING) 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_ = callback; 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (rv == OK) 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_->SetDelegate(this); 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return rv; 69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void QuicHttpStream::OnStreamReady(int rv) { 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(rv == OK || !stream_); 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (rv == OK) 74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_->SetDelegate(this); 75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ResetAndReturn(&callback_).Run(rv); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HttpResponseInfo* response, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(stream_); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!request_body_stream_); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!response_info_); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback.is_null()); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(response); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) QuicPriority priority = ConvertRequestPriorityToQuicPriority(priority_); 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_->set_priority(priority); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the serialized request headers. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyHeaderBlock headers; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &headers, 3, /*direct=*/true); 94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (session_->connection()->version() < QUIC_VERSION_9) { 95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) request_ = stream_->compressor()->CompressHeaders(headers); 96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) request_ = stream_->compressor()->CompressHeadersWithPriority(priority, 98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) headers); 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Log the actual request with the URL Request's net log. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_net_log_.AddEvent( 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Also log to the QuicSession's net log. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->net_log().AddEvent( 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS, 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the request body. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_ = request_info_->upload_data_stream; 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (request_body_stream_) { 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(rch): Can we be more precise about when to allocate 1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // raw_request_body_buf_. Removed the following check. DoReadRequestBody() 1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // was being called even if we didn't yet allocate raw_request_body_buf_. 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // && (request_body_stream_->size() || 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // request_body_stream_->is_chunked())) 1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use kMaxPacketSize as the buffer size, since the request 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // body data is written with this size at a time. 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): use a smarter value since we can't write an entire 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // packet due to overhead. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raw_request_body_buf_ = new IOBufferWithSize(kMaxPacketSize); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The request body buffer is empty at first. 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), 0); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the response info. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_ = response; 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_HEADERS; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = DoLoop(OK); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == ERR_IO_PENDING) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv > 0 ? OK : rv; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UploadProgress QuicHttpStream::GetUploadProgress() const { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!request_body_stream_) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return UploadProgress(); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return UploadProgress(request_body_stream_->position(), 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_->size()); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback.is_null()); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (stream_ == NULL) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return response_status_; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if we already have the response headers. If so, return synchronously. 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (response_headers_received_) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Still waiting for the response, return IO_PENDING. 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(callback_.is_null()); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const HttpResponseInfo* QuicHttpStream::GetResponseInfo() const { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return response_info_; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::ReadResponseBody( 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IOBuffer* buf, int buf_len, const CompletionCallback& callback) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(buf); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(buf_len); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback.is_null()); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have data buffered, complete the IO immediately. 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!response_body_.empty()) { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_read = 0; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (!response_body_.empty() && buf_len > 0) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<IOBufferWithSize> data = response_body_.front(); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_to_copy = std::min(buf_len, data->size()); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf_len -= bytes_to_copy; 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bytes_to_copy == data->size()) { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.pop_front(); 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_remaining = data->size() - bytes_to_copy; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_remaining); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.pop_front(); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.push_front(make_scoped_refptr(new_buffer)); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_read += bytes_to_copy; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return bytes_read; 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stream_) { 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the stream is already closed, there is no body to read. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return response_status_; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(callback_.is_null()); 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(!user_buffer_.get()); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(0, user_buffer_len_); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_ = buf; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_len_ = buf_len; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::Close(bool not_reusable) { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: the not_reusable flag has no meaning for SPDY streams. 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (stream_) { 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->SetDelegate(NULL); 214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(rch): use new CANCELLED error code here once quic 11 215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // is everywhere. 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_->Close(QUIC_ERROR_PROCESSING_STREAM); 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = NULL; 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpStream* QuicHttpStream::RenewStreamForAuth() { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::IsResponseBodyComplete() const { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return next_state_ == STATE_OPEN && !stream_; 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::CanFindEndOfResponse() const { 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::IsConnectionReused() const { 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): do something smarter here. 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return stream_ && stream_->id() > 1; 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::SetConnectionReused() { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // QUIC doesn't need an indicator here. 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::IsConnectionReusable() const { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // QUIC streams aren't considered reusable. 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(mmenke): Figure out what to do here. 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::GetSSLInfo(SSLInfo* ssl_info) { 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(stream_); 2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stream_->GetSSLInfo(ssl_info); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::GetSSLCertRequestInfo( 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SSLCertRequestInfo* cert_request_info) { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(stream_); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTIMPLEMENTED(); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::IsSpdyHttpStream() const { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::Drain(HttpNetworkSession* session) { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(false); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete this; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicHttpStream::SetPriority(RequestPriority priority) { 273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority_ = priority; 2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::OnSendData() { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): Change QUIC IO to provide notifications to the streams. 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::OnSendDataComplete(int status, bool* eof) { 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rch): Change QUIC IO to provide notifications to the streams. 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::OnDataReceived(const char* data, int length) { 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_NE(0, length); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Are we still reading the response headers. 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!response_headers_received_) { 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Grow the read buffer if necessary. 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (read_buf_->RemainingCapacity() < length) { 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) size_t additional_capacity = length - read_buf_->RemainingCapacity(); 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (additional_capacity < kHeaderBufInitialSize) 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) additional_capacity = kHeaderBufInitialSize; 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) read_buf_->SetCapacity(read_buf_->capacity() + additional_capacity); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(read_buf_->data(), data, length); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) read_buf_->set_offset(read_buf_->offset() + length); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = ParseResponseHeaders(); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != ERR_IO_PENDING && !callback_.is_null()) { 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(rv); 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (callback_.is_null()) { 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferResponseBody(data, length); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (length <= user_buffer_len_) { 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(user_buffer_->data(), data, length); 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(user_buffer_->data(), data, user_buffer_len_); 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int delta = length - user_buffer_len_; 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferResponseBody(data + user_buffer_len_, delta); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_ = NULL; 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_len_ = 0; 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(length); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::OnClose(QuicErrorCode error) { 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error != QUIC_NO_ERROR) { 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_status_ = ERR_QUIC_PROTOCOL_ERROR; 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!response_headers_received_) { 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_status_ = ERR_ABORTED; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = NULL; 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!callback_.is_null()) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(response_status_); 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::OnError(int error) { 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = NULL; 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_status_ = error; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!callback_.is_null()) 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(response_status_); 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicHttpStream::HasSendHeadersComplete() { 346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return next_state_ > STATE_SEND_HEADERS_COMPLETE; 347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::OnIOComplete(int rv) { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoLoop(rv); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != ERR_IO_PENDING && !callback_.is_null()) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(rv); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::DoCallback(int rv) { 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_NE(rv, ERR_IO_PENDING); 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback_.is_null()); 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The client callback can do anything, including destroying this class, 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so any pending callback must be issued after everything else is done. 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ResetAndReturn(&callback_).Run(rv); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoLoop(int rv) { 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) do { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) State state = next_state_; 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_NONE; 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state) { 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_HEADERS: 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendHeaders(); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_HEADERS_COMPLETE: 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendHeadersComplete(rv); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_READ_REQUEST_BODY: 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoReadRequestBody(); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_READ_REQUEST_BODY_COMPLETE: 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoReadRequestBodyComplete(rv); 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_BODY: 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendBody(); 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_BODY_COMPLETE: 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendBodyComplete(rv); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_OPEN: 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "next_state_: " << next_state_; 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (next_state_ != STATE_NONE && next_state_ != STATE_OPEN && 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv != ERR_IO_PENDING); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendHeaders() { 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stream_) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_UNEXPECTED; 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_upload_data = request_body_stream_ != NULL; 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_HEADERS_COMPLETE; 41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return stream_->WriteStreamData( 41358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_, !has_upload_data, 41458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendHeadersComplete(int rv) { 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv < 0) 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = request_body_stream_ ? 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STATE_READ_REQUEST_BODY : STATE_OPEN; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoReadRequestBody() { 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_READ_REQUEST_BODY_COMPLETE; 429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return request_body_stream_->Read( 430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) raw_request_body_buf_.get(), 431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) raw_request_body_buf_->size(), 432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoReadRequestBodyComplete(int rv) { 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |rv| is the result of read from the request body from the last call to 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DoSendBody(). 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv < 0) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), rv); 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == 0) { // Reached the end. 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(request_body_stream_->IsEOF()); 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_BODY; 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendBody() { 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stream_) 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_UNEXPECTED; 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(request_body_stream_); 455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(request_body_buf_.get()); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool eof = request_body_stream_->IsEOF(); 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int len = request_body_buf_->BytesRemaining(); 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (len > 0 || eof) { 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_BODY_COMPLETE; 46058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::StringPiece data(request_body_buf_->data(), len); 46158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return stream_->WriteStreamData( 46258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) data, eof, 46358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 46658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_state_ = STATE_OPEN; 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendBodyComplete(int rv) { 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv < 0) 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 47458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_body_buf_->DidConsume(request_body_buf_->BytesRemaining()); 47558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 47658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!request_body_stream_->IsEOF()) { 47758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_state_ = STATE_READ_REQUEST_BODY; 47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return OK; 47958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 48058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_state_ = STATE_OPEN; 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::ParseResponseHeaders() { 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyFramer framer(SPDY3); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyHeaderBlock headers; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* data = read_buf_->StartOfBuffer(); 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &headers); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (len == 0) { 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Save the remaining received data. 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t delta = read_buf_len - len; 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delta > 0) { 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferResponseBody(data + len, delta); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The URLRequest logs these headers, so only log to the QuicSession's 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // net log. 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->net_log().AddEvent( 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS, 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SpdyHeadersToHttpResponse(headers, 3, response_info_)) { 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(WARNING) << "Invalid headers"; 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_QUIC_PROTOCOL_ERROR; 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the peer's IP address and port into the response. 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPEndPoint address = stream_->GetPeerAddress(); 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->socket_address = HostPortPair::FromIPEndPoint(address); 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->connection_info = 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3; 518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) response_info_->vary_data 519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) .Init(*request_info_, *response_info_->headers.get()); 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->was_npn_negotiated = true; 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->npn_negotiated_protocol = "quic/1+spdy/3"; 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_headers_received_ = true; 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::BufferResponseBody(const char* data, int length) { 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (length == 0) 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IOBufferWithSize* io_buffer = new IOBufferWithSize(length); 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(io_buffer->data(), data, length); 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.push_back(make_scoped_refptr(io_buffer)); 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace net 536