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" 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/metrics/histogram.h" 95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_response_headers.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_util.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_client_session.h" 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/quic/quic_http_utils.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_reliable_client_stream.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_utils.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/socket/next_proto.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_frame_builder.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_framer.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_http_utils.h" 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/ssl/ssl_info.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const size_t kHeaderBufInitialSize = 4096; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)QuicHttpStream::QuicHttpStream(const base::WeakPtr<QuicClientSession>& session) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : next_state_(STATE_NONE), 30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session_(session), 318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) session_error_(OK), 328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) was_handshake_confirmed_(session->IsCryptoHandshakeConfirmed()), 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_(NULL), 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_info_(NULL), 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_(NULL), 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority_(MINIMUM_PRIORITY), 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_(NULL), 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_status_(OK), 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_headers_received_(false), 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) read_buf_(new GrowableIOBuffer()), 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) closed_stream_received_bytes_(0), 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_len_(0), 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(session_); 458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) session_->AddObserver(this); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicHttpStream::~QuicHttpStream() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(false); 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (session_) 518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) session_->RemoveObserver(this); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestPriority priority, 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BoundNetLog& stream_net_log, 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(!stream_); 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!session_) 608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED : 618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ERR_QUIC_HANDSHAKE_FAILED; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (request_info->url.SchemeIsSecure()) { 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SSLInfo ssl_info; 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool secure_session = session_->GetSSLInfo(&ssl_info) && ssl_info.cert; 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.SecureResourceSecureSession", 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch secure_session); 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!secure_session) 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ERR_REQUEST_FOR_SECURE_RESOURCE_OVER_INSECURE_QUIC; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_net_log_ = stream_net_log; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_info_ = request_info; 742f22f038970e0d1927c41b04bbf5589bd12c5316Torne (Richard Coles) request_time_ = base::Time::Now(); 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority_ = priority; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) int rv = stream_request_.StartRequest( 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) session_, &stream_, base::Bind(&QuicHttpStream::OnStreamReady, 79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) weak_factory_.GetWeakPtr())); 808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (rv == ERR_IO_PENDING) { 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) callback_ = callback; 828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else if (rv == OK) { 83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_->SetDelegate(this); 848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else if (!was_handshake_confirmed_) { 858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) rv = ERR_QUIC_HANDSHAKE_FAILED; 868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return rv; 89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void QuicHttpStream::OnStreamReady(int rv) { 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(rv == OK || !stream_); 938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (rv == OK) { 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_->SetDelegate(this); 958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else if (!was_handshake_confirmed_) { 968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) rv = ERR_QUIC_HANDSHAKE_FAILED; 978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ResetAndReturn(&callback_).Run(rv); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HttpResponseInfo* response, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(stream_); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!request_body_stream_); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!response_info_); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback.is_null()); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(response); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) QuicPriority priority = ConvertRequestPriorityToQuicPriority(priority_); 112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stream_->set_priority(priority); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the serialized request headers. 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &request_headers_, SPDY3, /*direct=*/true); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the request body. 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_ = request_info_->upload_data_stream; 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (request_body_stream_) { 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(rch): Can we be more precise about when to allocate 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // raw_request_body_buf_. Removed the following check. DoReadRequestBody() 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // was being called even if we didn't yet allocate raw_request_body_buf_. 1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // && (request_body_stream_->size() || 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // request_body_stream_->is_chunked())) 1256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // Use 10 packets as the body buffer size to give enough space to 1266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // help ensure we don't often send out partial packets. 1276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) raw_request_body_buf_ = new IOBufferWithSize(10 * kMaxPacketSize); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The request body buffer is empty at first. 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), 0); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the response info. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_ = response; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_HEADERS; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = DoLoop(OK); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == ERR_IO_PENDING) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv > 0 ? OK : rv; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)UploadProgress QuicHttpStream::GetUploadProgress() const { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!request_body_stream_) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return UploadProgress(); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return UploadProgress(request_body_stream_->position(), 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_->size()); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback.is_null()); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (stream_ == NULL) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return response_status_; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check if we already have the response headers. If so, return synchronously. 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (response_headers_received_) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Still waiting for the response, return IO_PENDING. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(callback_.is_null()); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::ReadResponseBody( 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IOBuffer* buf, int buf_len, const CompletionCallback& callback) { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(buf); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(buf_len); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback.is_null()); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we have data buffered, complete the IO immediately. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!response_body_.empty()) { 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_read = 0; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (!response_body_.empty() && buf_len > 0) { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<IOBufferWithSize> data = response_body_.front(); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_to_copy = std::min(buf_len, data->size()); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf_len -= bytes_to_copy; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bytes_to_copy == data->size()) { 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.pop_front(); 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_remaining = data->size() - bytes_to_copy; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_remaining); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.pop_front(); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.push_front(make_scoped_refptr(new_buffer)); 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_read += bytes_to_copy; 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return bytes_read; 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stream_) { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the stream is already closed, there is no body to read. 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return response_status_; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(callback_.is_null()); 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(!user_buffer_.get()); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(0, user_buffer_len_); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_ = buf; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_len_ = buf_len; 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::Close(bool not_reusable) { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: the not_reusable flag has no meaning for SPDY streams. 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (stream_) { 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) closed_stream_received_bytes_ = stream_->stream_bytes_read(); 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->SetDelegate(NULL); 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_->Reset(QUIC_STREAM_CANCELLED); 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) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int64 QuicHttpStream::GetTotalReceivedBytes() const { 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (stream_) { 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return stream_->stream_bytes_read(); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return closed_stream_received_bytes_; 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(mmenke): Figure out what to do here. 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::GetSSLInfo(SSLInfo* ssl_info) { 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(stream_); 2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch stream_->GetSSLInfo(ssl_info); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::GetSSLCertRequestInfo( 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SSLCertRequestInfo* cert_request_info) { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(stream_); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTIMPLEMENTED(); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicHttpStream::IsSpdyHttpStream() const { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::Drain(HttpNetworkSession* session) { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(false); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete this; 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void QuicHttpStream::SetPriority(RequestPriority priority) { 281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) priority_ = priority; 2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::OnDataReceived(const char* data, int length) { 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_NE(0, length); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Are we still reading the response headers. 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!response_headers_received_) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Grow the read buffer if necessary. 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (read_buf_->RemainingCapacity() < length) { 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) size_t additional_capacity = length - read_buf_->RemainingCapacity(); 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (additional_capacity < kHeaderBufInitialSize) 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) additional_capacity = kHeaderBufInitialSize; 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) read_buf_->SetCapacity(read_buf_->capacity() + additional_capacity); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(read_buf_->data(), data, length); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) read_buf_->set_offset(read_buf_->offset() + length); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = ParseResponseHeaders(); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != ERR_IO_PENDING && !callback_.is_null()) { 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(rv); 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (callback_.is_null()) { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferResponseBody(data, length); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (length <= user_buffer_len_) { 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(user_buffer_->data(), data, length); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(user_buffer_->data(), data, user_buffer_len_); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int delta = length - user_buffer_len_; 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferResponseBody(data + user_buffer_len_, delta); 3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) length = user_buffer_len_; 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_ = NULL; 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_buffer_len_ = 0; 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(length); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::OnClose(QuicErrorCode error) { 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (error != QUIC_NO_ERROR) { 3268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) response_status_ = was_handshake_confirmed_ ? 3278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ERR_QUIC_PROTOCOL_ERROR : ERR_QUIC_HANDSHAKE_FAILED; 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!response_headers_received_) { 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_status_ = ERR_ABORTED; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) closed_stream_received_bytes_ = stream_->stream_bytes_read(); 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; 3408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) response_status_ = was_handshake_confirmed_ ? 3418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) error : ERR_QUIC_HANDSHAKE_FAILED; 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!callback_.is_null()) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(response_status_); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool QuicHttpStream::HasSendHeadersComplete() { 347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return next_state_ > STATE_SEND_HEADERS_COMPLETE; 348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicHttpStream::OnCryptoHandshakeConfirmed() { 3518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) was_handshake_confirmed_ = true; 3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 3538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void QuicHttpStream::OnSessionClosed(int error) { 3558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) session_error_ = error; 3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) session_.reset(); 3578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 3588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::OnIOComplete(int rv) { 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoLoop(rv); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != ERR_IO_PENDING && !callback_.is_null()) { 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DoCallback(rv); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::DoCallback(int rv) { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_NE(rv, ERR_IO_PENDING); 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(!callback_.is_null()); 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The client callback can do anything, including destroying this class, 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so any pending callback must be issued after everything else is done. 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ResetAndReturn(&callback_).Run(rv); 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoLoop(int rv) { 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) do { 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) State state = next_state_; 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_NONE; 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (state) { 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_HEADERS: 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendHeaders(); 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_HEADERS_COMPLETE: 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendHeadersComplete(rv); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_READ_REQUEST_BODY: 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoReadRequestBody(); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_READ_REQUEST_BODY_COMPLETE: 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoReadRequestBodyComplete(rv); 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_BODY: 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendBody(); 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_SEND_BODY_COMPLETE: 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = DoSendBodyComplete(rv); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case STATE_OPEN: 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(OK, rv); 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "next_state_: " << next_state_; 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (next_state_ != STATE_NONE && next_state_ != STATE_OPEN && 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv != ERR_IO_PENDING); 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendHeaders() { 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stream_) 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_UNEXPECTED; 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Log the actual request with the URL Request's net log. 420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream_net_log_.AddEvent( 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NetLog::TYPE_HTTP_TRANSACTION_QUIC_SEND_REQUEST_HEADERS, 4220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&QuicRequestNetLogCallback, stream_->id(), &request_headers_, 4230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch priority_)); 424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Also log to the QuicSession's net log. 425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream_->net_log().AddEvent( 426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS, 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&QuicRequestNetLogCallback, stream_->id(), &request_headers_, 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch priority_)); 429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_upload_data = request_body_stream_ != NULL; 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_HEADERS_COMPLETE; 43323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int rv = stream_->WriteHeaders(request_headers_, !has_upload_data, NULL); 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_headers_.clear(); 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return rv; 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendHeadersComplete(int rv) { 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv < 0) 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = request_body_stream_ ? 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STATE_READ_REQUEST_BODY : STATE_OPEN; 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoReadRequestBody() { 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_READ_REQUEST_BODY_COMPLETE; 450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return request_body_stream_->Read( 451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) raw_request_body_buf_.get(), 452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) raw_request_body_buf_->size(), 453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoReadRequestBodyComplete(int rv) { 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |rv| is the result of read from the request body from the last call to 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DoSendBody(). 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv < 0) 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), rv); 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == 0) { // Reached the end. 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(request_body_stream_->IsEOF()); 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_BODY; 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendBody() { 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stream_) 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_UNEXPECTED; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(request_body_stream_); 476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(request_body_buf_.get()); 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool eof = request_body_stream_->IsEOF(); 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int len = request_body_buf_->BytesRemaining(); 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (len > 0 || eof) { 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_state_ = STATE_SEND_BODY_COMPLETE; 48158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::StringPiece data(request_body_buf_->data(), len); 48258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return stream_->WriteStreamData( 48358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) data, eof, 48458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 48758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_state_ = STATE_OPEN; 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::DoSendBodyComplete(int rv) { 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv < 0) 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 49558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) request_body_buf_->DidConsume(request_body_buf_->BytesRemaining()); 49658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 49758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!request_body_stream_->IsEOF()) { 49858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_state_ = STATE_READ_REQUEST_BODY; 49958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return OK; 50058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 50158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 50258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) next_state_ = STATE_OPEN; 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int QuicHttpStream::ParseResponseHeaders() { 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyFramer framer(SPDY3); 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyHeaderBlock headers; 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* data = read_buf_->StartOfBuffer(); 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &headers); 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (len == 0) { 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Save the remaining received data. 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t delta = read_buf_len - len; 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delta > 0) { 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BufferResponseBody(data + len, delta); 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The URLRequest logs these headers, so only log to the QuicSession's 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // net log. 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_->net_log().AddEvent( 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS, 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!SpdyHeadersToHttpResponse(headers, SPDY3, response_info_)) { 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DLOG(WARNING) << "Invalid headers"; 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_QUIC_PROTOCOL_ERROR; 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Put the peer's IP address and port into the response. 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPEndPoint address = stream_->GetPeerAddress(); 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->socket_address = HostPortPair::FromIPEndPoint(address); 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->connection_info = 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3; 539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) response_info_->vary_data 540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) .Init(*request_info_, *response_info_->headers.get()); 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->was_npn_negotiated = true; 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_info_->npn_negotiated_protocol = "quic/1+spdy/3"; 5432f22f038970e0d1927c41b04bbf5589bd12c5316Torne (Richard Coles) response_info_->response_time = base::Time::Now(); 5442f22f038970e0d1927c41b04bbf5589bd12c5316Torne (Richard Coles) response_info_->request_time = request_time_; 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_headers_received_ = true; 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicHttpStream::BufferResponseBody(const char* data, int length) { 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (length == 0) 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IOBufferWithSize* io_buffer = new IOBufferWithSize(length); 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(io_buffer->data(), data, length); 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) response_body_.push_back(make_scoped_refptr(io_buffer)); 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace net 559