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.
5 #include "net/tools/quic/quic_spdy_server_stream.h"
7 #include "net/quic/quic_session.h"
8 #include "net/spdy/spdy_framer.h"
9 #include "net/tools/quic/spdy_utils.h"
16 static const size_t kHeaderBufInitialSize = 4096;
18 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
20 : QuicReliableServerStream(id, session),
21 read_buf_(new GrowableIOBuffer()),
22 request_headers_received_(false) {
25 QuicSpdyServerStream::~QuicSpdyServerStream() {
28 uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 length) {
29 uint32 total_bytes_processed = 0;
31 // Are we still reading the request headers.
32 if (!request_headers_received_) {
33 // Grow the read buffer if necessary.
34 if (read_buf_->RemainingCapacity() < (int)length) {
35 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize);
37 memcpy(read_buf_->data(), data, length);
38 read_buf_->set_offset(read_buf_->offset() + length);
39 ParseRequestHeaders();
41 mutable_body()->append(data + total_bytes_processed,
42 length - total_bytes_processed);
47 void QuicSpdyServerStream::TerminateFromPeer(bool half_close) {
48 ReliableQuicStream::TerminateFromPeer(half_close);
49 // This is a full close: do not send a response.
53 if (write_side_closed() || fin_buffered()) {
57 if (!request_headers_received_) {
58 SendErrorResponse(); // We're not done writing headers.
59 } else if ((headers().content_length_status() ==
60 BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
61 mutable_body()->size() != headers().content_length()) {
62 SendErrorResponse(); // Invalid content length
68 void QuicSpdyServerStream::SendHeaders(
69 const BalsaHeaders& response_headers) {
70 SpdyHeaderBlock header_block =
71 SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers);
73 string headers_string;
74 headers_string = session()->compressor()->CompressHeaders(header_block);
76 WriteData(headers_string, false);
79 int QuicSpdyServerStream::ParseRequestHeaders() {
80 size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
81 SpdyFramer framer(SPDY3);
82 SpdyHeaderBlock headers;
83 char* data = read_buf_->StartOfBuffer();
84 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(),
90 if (!SpdyUtils::FillBalsaRequestHeaders(headers, mutable_headers())) {
95 size_t delta = read_buf_len - len;
97 mutable_body()->append(data + len, delta);
100 request_headers_received_ = true;