- add sources.
[platform/framework/web/crosswalk.git] / src / net / tools / quic / quic_spdy_server_stream.cc
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/quic/quic_session.h"
8 #include "net/spdy/spdy_framer.h"
9 #include "net/tools/quic/spdy_utils.h"
10
11 using std::string;
12
13 namespace net {
14 namespace tools {
15
16 static const size_t kHeaderBufInitialSize = 4096;
17
18 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
19                                            QuicSession* session)
20     : QuicReliableServerStream(id, session),
21       read_buf_(new GrowableIOBuffer()),
22       request_headers_received_(false) {
23 }
24
25 QuicSpdyServerStream::~QuicSpdyServerStream() {
26 }
27
28 uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 length) {
29   uint32 total_bytes_processed = 0;
30
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);
36     }
37     memcpy(read_buf_->data(), data, length);
38     read_buf_->set_offset(read_buf_->offset() + length);
39     ParseRequestHeaders();
40   } else {
41     mutable_body()->append(data + total_bytes_processed,
42                            length - total_bytes_processed);
43   }
44   return length;
45 }
46
47 void QuicSpdyServerStream::TerminateFromPeer(bool half_close) {
48   ReliableQuicStream::TerminateFromPeer(half_close);
49   // This is a full close: do not send a response.
50   if (!half_close) {
51     return;
52   }
53   if (write_side_closed() || fin_buffered()) {
54     return;
55   }
56
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
63   } else {
64     SendResponse();
65   }
66 }
67
68 void QuicSpdyServerStream::SendHeaders(
69     const BalsaHeaders& response_headers) {
70   SpdyHeaderBlock header_block =
71       SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers);
72
73   string headers_string;
74   headers_string = session()->compressor()->CompressHeaders(header_block);
75
76   WriteData(headers_string, false);
77 }
78
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(),
85                                                &headers);
86   if (len == 0) {
87     return -1;
88   }
89
90   if (!SpdyUtils::FillBalsaRequestHeaders(headers, mutable_headers())) {
91     SendErrorResponse();
92     return -1;
93   }
94
95   size_t delta = read_buf_len - len;
96   if (delta > 0) {
97     mutable_body()->append(data + len, delta);
98   }
99
100   request_headers_received_ = true;
101   return len;
102 }
103
104 }  // namespace tools
105 }  // namespace net