quic_spdy_server_stream.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/tools/quic/quic_spdy_server_stream.h" 6 7#include "net/spdy/spdy_framer.h" 8#include "net/tools/quic/spdy_utils.h" 9 10using std::string; 11 12namespace net { 13namespace tools { 14 15static const size_t kHeaderBufInitialSize = 4096; 16 17QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, 18 QuicSession* session) 19 : QuicReliableServerStream(id, session), 20 read_buf_(new GrowableIOBuffer()), 21 request_headers_received_(false) { 22} 23 24QuicSpdyServerStream::~QuicSpdyServerStream() { 25} 26 27uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 length) { 28 uint32 total_bytes_processed = 0; 29 30 // Are we still reading the request headers. 31 if (!request_headers_received_) { 32 // Grow the read buffer if necessary. 33 if (read_buf_->RemainingCapacity() < (int)length) { 34 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 35 } 36 memcpy(read_buf_->data(), data, length); 37 read_buf_->set_offset(read_buf_->offset() + length); 38 ParseRequestHeaders(); 39 } else { 40 mutable_body()->append(data + total_bytes_processed, 41 length - total_bytes_processed); 42 } 43 return length; 44} 45 46void QuicSpdyServerStream::TerminateFromPeer(bool half_close) { 47 ReliableQuicStream::TerminateFromPeer(half_close); 48 // This is a full close: do not send a response. 49 if (!half_close) { 50 return; 51 } 52 if (!request_headers_received_) { 53 SendErrorResponse(); // We're not done writing headers. 54 } else if ((headers().content_length_status() == 55 BalsaHeadersEnums::VALID_CONTENT_LENGTH) && 56 mutable_body()->size() != headers().content_length()) { 57 SendErrorResponse(); // Invalid content length 58 } else { 59 SendResponse(); 60 } 61} 62 63void QuicSpdyServerStream::SendHeaders( 64 const BalsaHeaders& response_headers) { 65 string headers = 66 SpdyUtils::SerializeResponseHeaders(response_headers); 67 WriteData(headers, false); 68} 69 70int QuicSpdyServerStream::ParseRequestHeaders() { 71 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 72 SpdyFramer framer(3); 73 SpdyHeaderBlock headers; 74 char* data = read_buf_->StartOfBuffer(); 75 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 76 &headers); 77 if (len == 0) { 78 return -1; 79 } 80 81 if (!SpdyUtils::FillBalsaRequestHeaders(headers, mutable_headers())) { 82 SendErrorResponse(); 83 return -1; 84 } 85 86 size_t delta = read_buf_len - len; 87 if (delta > 0) { 88 mutable_body()->append(data + len, delta); 89 } 90 91 request_headers_received_ = true; 92 return len; 93} 94 95} // namespace tools 96} // namespace net 97