1 // Copyright 2014 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/quic/quic_spdy_server_stream.h"
7 #include "base/memory/singleton.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "net/quic/quic_in_memory_cache.h"
10 #include "net/quic/quic_session.h"
11 #include "net/quic/spdy_utils.h"
12 #include "net/spdy/spdy_framer.h"
13 #include "net/spdy/spdy_header_block.h"
14 #include "net/spdy/spdy_http_utils.h"
16 using base::StringPiece
;
21 static const size_t kHeaderBufInitialSize
= 4096;
23 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id
,
25 : QuicDataStream(id
, session
),
26 read_buf_(new GrowableIOBuffer()),
27 request_headers_received_(false) {
28 read_buf_
->SetCapacity(kHeaderBufInitialSize
);
31 QuicSpdyServerStream::~QuicSpdyServerStream() {
34 uint32
QuicSpdyServerStream::ProcessData(const char* data
, uint32 data_len
) {
35 if (data_len
> INT_MAX
) {
36 LOG(DFATAL
) << "Data length too long: " << data_len
;
39 // Are we still reading the request headers.
40 if (!request_headers_received_
) {
41 // Grow the read buffer if necessary.
42 while (read_buf_
->RemainingCapacity() < static_cast<int>(data_len
)) {
43 read_buf_
->SetCapacity(read_buf_
->capacity() * 2);
45 memcpy(read_buf_
->data(), data
, data_len
);
46 read_buf_
->set_offset(read_buf_
->offset() + data_len
);
47 // Try parsing the request headers. This will set request_headers_received_
48 // if successful; if not, it will be tried again with more data.
49 ParseRequestHeaders();
51 body_
.append(data
, data_len
);
56 void QuicSpdyServerStream::OnFinRead() {
57 ReliableQuicStream::OnFinRead();
58 if (write_side_closed() || fin_buffered()) {
62 if (!request_headers_received_
) {
63 SendErrorResponse(); // We're not done reading headers.
67 SpdyHeaderBlock::const_iterator it
= headers_
.find("content-length");
68 size_t content_length
;
69 if (it
!= headers_
.end() &&
70 (!base::StringToSizeT(it
->second
, &content_length
) ||
71 body_
.size() != content_length
)) {
72 SendErrorResponse(); // Invalid content length
79 // Try parsing the request headers. If successful, sets
80 // request_headers_received_. If not successful, it can just be tried again once
82 void QuicSpdyServerStream::ParseRequestHeaders() {
83 SpdyFramer
framer((kDefaultSpdyMajorVersion
));
84 const char* data
= read_buf_
->StartOfBuffer();
85 size_t read_buf_len
= static_cast<size_t>(read_buf_
->offset());
86 size_t len
= framer
.ParseHeaderBlockInBuffer(data
, read_buf_len
, &headers_
);
88 // Not enough data yet, presumably. (If we still don't succeed by the end of
89 // the stream, then we'll error in OnFinRead().)
93 // Headers received and parsed: extract the request URL.
94 request_url_
= GetUrlFromHeaderBlock(headers_
,
95 kDefaultSpdyMajorVersion
,
97 if (!request_url_
.is_valid()) {
102 // Add any data past the headers to the request body.
103 size_t delta
= read_buf_len
- len
;
105 body_
.append(data
+ len
, delta
);
108 request_headers_received_
= true;
111 void QuicSpdyServerStream::SendResponse() {
112 // Find response in cache. If not found, send error response.
113 const QuicInMemoryCache::Response
* response
=
114 QuicInMemoryCache::GetInstance()->GetResponse(request_url_
);
115 if (response
== NULL
) {
120 if (response
->response_type() == QuicInMemoryCache::CLOSE_CONNECTION
) {
121 DVLOG(1) << "Special response: closing connection.";
122 CloseConnection(QUIC_NO_ERROR
);
126 if (response
->response_type() == QuicInMemoryCache::IGNORE_REQUEST
) {
127 DVLOG(1) << "Special response: ignoring request.";
131 DVLOG(1) << "Sending response for stream " << id();
132 SendHeadersAndBody(response
->headers(), response
->body());
135 void QuicSpdyServerStream::SendErrorResponse() {
136 DVLOG(1) << "Sending error response for stream " << id();
137 scoped_refptr
<HttpResponseHeaders
> headers
138 = new HttpResponseHeaders(string("HTTP/1.1 500 Server Error") + '\0' +
139 "content-length: 3" + '\0' + '\0');
140 SendHeadersAndBody(*headers
, "bad");
143 void QuicSpdyServerStream::SendHeadersAndBody(
144 const HttpResponseHeaders
& response_headers
,
146 // We only support SPDY and HTTP, and neither handles bidirectional streaming.
147 if (!read_side_closed()) {
151 SpdyHeaderBlock header_block
;
152 CreateSpdyHeadersFromHttpResponse(response_headers
,
153 kDefaultSpdyMajorVersion
,
156 WriteHeaders(header_block
, body
.empty(), NULL
);
159 WriteOrBufferData(body
, true, NULL
);