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. 4 5 #include "net/quic/quic_spdy_server_stream.h" 6 7 #include "base/memory/singleton.h" 8 #include "net/quic/quic_in_memory_cache.h" 9 #include "net/quic/quic_session.h" 10 #include "net/spdy/spdy_framer.h" 11 #include "net/tools/quic/spdy_utils.h" 12 13 using base::StringPiece; 14 using std::string; 15 using net::tools::SpdyUtils; 16 17 namespace net { 18 19 static const size_t kHeaderBufInitialSize = 4096; 20 21 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, 22 QuicSession* session) 23 : QuicDataStream(id, session), 24 read_buf_(new GrowableIOBuffer()), 25 request_headers_received_(false) { 26 } 27 28 QuicSpdyServerStream::~QuicSpdyServerStream() { 29 } 30 31 uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) { 32 uint32 total_bytes_processed = 0; 33 34 // Are we still reading the request headers. 35 if (!request_headers_received_) { 36 // Grow the read buffer if necessary. 37 if (read_buf_->RemainingCapacity() < (int)data_len) { 38 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 39 } 40 memcpy(read_buf_->data(), data, data_len); 41 read_buf_->set_offset(read_buf_->offset() + data_len); 42 ParseRequestHeaders(); 43 } else { 44 body_.append(data + total_bytes_processed, 45 data_len - total_bytes_processed); 46 } 47 return data_len; 48 } 49 50 void QuicSpdyServerStream::OnFinRead() { 51 ReliableQuicStream::OnFinRead(); 52 if (write_side_closed() || fin_buffered()) { 53 return; 54 } 55 56 if (!request_headers_received_) { 57 SendErrorResponse(); // We're not done reading headers. 58 } else if ((headers_.content_length_status() == 59 BalsaHeadersEnums::VALID_CONTENT_LENGTH) && 60 body_.size() != headers_.content_length()) { 61 SendErrorResponse(); // Invalid content length 62 } else { 63 SendResponse(); 64 } 65 } 66 67 int QuicSpdyServerStream::ParseRequestHeaders() { 68 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 69 SpdyFramer framer(SPDY3); 70 SpdyHeaderBlock headers; 71 char* data = read_buf_->StartOfBuffer(); 72 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 73 &headers); 74 if (len == 0) { 75 return -1; 76 } 77 78 if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) { 79 SendErrorResponse(); 80 return -1; 81 } 82 83 size_t delta = read_buf_len - len; 84 if (delta > 0) { 85 body_.append(data + len, delta); 86 } 87 88 request_headers_received_ = true; 89 return len; 90 } 91 92 void QuicSpdyServerStream::SendResponse() { 93 // Find response in cache. If not found, send error response. 94 const QuicInMemoryCache::Response* response = 95 QuicInMemoryCache::GetInstance()->GetResponse(headers_); 96 if (response == NULL) { 97 SendErrorResponse(); 98 return; 99 } 100 101 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) { 102 DVLOG(1) << "Special response: closing connection."; 103 CloseConnection(QUIC_NO_ERROR); 104 return; 105 } 106 107 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) { 108 DVLOG(1) << "Special response: ignoring request."; 109 return; 110 } 111 112 DVLOG(1) << "Sending response for stream " << id(); 113 SendHeadersAndBody(response->headers(), response->body()); 114 } 115 116 void QuicSpdyServerStream::SendErrorResponse() { 117 DVLOG(1) << "Sending error response for stream " << id(); 118 BalsaHeaders headers; 119 headers.SetResponseFirstlineFromStringPieces( 120 "HTTP/1.1", "500", "Server Error"); 121 headers.ReplaceOrAppendHeader("content-length", "3"); 122 SendHeadersAndBody(headers, "bad"); 123 } 124 125 void QuicSpdyServerStream::SendHeadersAndBody( 126 const BalsaHeaders& response_headers, 127 StringPiece body) { 128 // We only support SPDY and HTTP, and neither handles bidirectional streaming. 129 if (!read_side_closed()) { 130 CloseReadSide(); 131 } 132 133 SpdyHeaderBlock header_block = 134 SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers); 135 136 WriteHeaders(header_block, body.empty(), NULL); 137 138 if (!body.empty()) { 139 WriteOrBufferData(body, true, NULL); 140 } 141 } 142 143 } // namespace net 144