1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_spdy_client_stream.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_framer.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_client_session.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/spdy_utils.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StringPiece; 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using std::string; 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net { 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools { 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const size_t kHeaderBufInitialSize = 4096; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id, 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicClientSession* session) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : QuicDataStream(id, session), 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read_buf_(new GrowableIOBuffer()), 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response_headers_received_(false), 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) header_bytes_read_(0), 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) header_bytes_written_(0) { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicSpdyClientStream::~QuicSpdyClientStream() { 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) { 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!write_side_closed()) { 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Got a response before the request was complete. " 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "Aborting request."; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CloseWriteSide(); 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) QuicDataStream::OnStreamFrame(frame); 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin, 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t frame_len) { 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) header_bytes_read_ = frame_len; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicDataStream::OnStreamHeadersComplete(fin, frame_len); 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint32 QuicSpdyClientStream::ProcessData(const char* data, 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 data_len) { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int total_bytes_processed = 0; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Are we still reading the response headers. 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!response_headers_received_) { 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Grow the read buffer if necessary. 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (read_buf_->RemainingCapacity() < (int)data_len) { 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) memcpy(read_buf_->data(), data, data_len); 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) read_buf_->set_offset(read_buf_->offset() + data_len); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ParseResponseHeaders(); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data_.append(data + total_bytes_processed, 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data_len - total_bytes_processed); 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return data_len; 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void QuicSpdyClientStream::OnFinRead() { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ReliableQuicStream::OnFinRead(); 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!response_headers_received_) { 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Reset(QUIC_BAD_APPLICATION_PAYLOAD); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if ((headers().content_length_status() == 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BalsaHeadersEnums::VALID_CONTENT_LENGTH) && 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data_.size() != headers().content_length()) { 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Reset(QUIC_BAD_APPLICATION_PAYLOAD); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers, 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece body, 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool fin) { 80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyHeaderBlock header_block = 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyUtils::RequestHeadersToSpdyHeaders(headers); 82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool send_fin_with_headers = fin && body.empty(); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t bytes_sent = body.size(); 8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) header_bytes_written_ = WriteHeaders( 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) header_block, send_fin_with_headers, NULL); 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_sent += header_bytes_written_; 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!body.empty()) { 9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) WriteOrBufferData(body, fin, NULL); 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return bytes_sent; 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int QuicSpdyClientStream::ParseResponseHeaders() { 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyFramer framer(SPDY3); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyHeaderBlock headers; 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) char* data = read_buf_->StartOfBuffer(); 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &headers); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (len == 0) { 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return -1; 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!SpdyUtils::FillBalsaResponseHeaders(headers, &headers_)) { 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Reset(QUIC_BAD_APPLICATION_PAYLOAD); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return -1; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) response_headers_received_ = true; 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t delta = read_buf_len - len; 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (delta > 0) { 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data_.append(data + len, delta); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return len; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Sends body data to the server and returns the number of bytes sent. 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSpdyClientStream::SendBody(const string& data, bool fin) { 12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) WriteOrBufferData(data, fin, NULL); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace tools 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace net 128