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