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 session()->compressor()->CompressHeaders(header_block
);
75 WriteData(headers
, false);
78 int QuicSpdyServerStream::ParseRequestHeaders() {
79 size_t read_buf_len
= static_cast<size_t>(read_buf_
->offset());
80 SpdyFramer
framer(SPDY3
);
81 SpdyHeaderBlock headers
;
82 char* data
= read_buf_
->StartOfBuffer();
83 size_t len
= framer
.ParseHeaderBlockInBuffer(data
, read_buf_
->offset(),
89 if (!SpdyUtils::FillBalsaRequestHeaders(headers
, mutable_headers())) {
94 size_t delta
= read_buf_len
- len
;
96 mutable_body()->append(data
+ len
, delta
);
99 request_headers_received_
= true;