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 "base/memory/singleton.h" 8 #include "net/quic/quic_session.h" 9 #include "net/spdy/spdy_framer.h" 10 #include "net/tools/quic/quic_in_memory_cache.h" 11 #include "net/tools/quic/spdy_utils.h" 12 13 using base::StringPiece; 14 using std::string; 15 16 namespace net { 17 namespace tools { 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 length) { 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)length) { 38 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 39 } 40 memcpy(read_buf_->data(), data, length); 41 read_buf_->set_offset(read_buf_->offset() + length); 42 ParseRequestHeaders(); 43 } else { 44 body_.append(data + total_bytes_processed, length - total_bytes_processed); 45 } 46 return length; 47 } 48 49 void QuicSpdyServerStream::OnFinRead() { 50 ReliableQuicStream::OnFinRead(); 51 if (write_side_closed() || fin_buffered()) { 52 return; 53 } 54 55 if (!request_headers_received_) { 56 SendErrorResponse(); // We're not done reading headers. 57 } else if ((headers_.content_length_status() == 58 BalsaHeadersEnums::VALID_CONTENT_LENGTH) && 59 body_.size() != headers_.content_length()) { 60 SendErrorResponse(); // Invalid content length 61 } else { 62 SendResponse(); 63 } 64 } 65 66 int QuicSpdyServerStream::ParseRequestHeaders() { 67 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 68 SpdyFramer framer(SPDY3); 69 SpdyHeaderBlock headers; 70 char* data = read_buf_->StartOfBuffer(); 71 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 72 &headers); 73 if (len == 0) { 74 return -1; 75 } 76 77 if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) { 78 SendErrorResponse(); 79 return -1; 80 } 81 82 size_t delta = read_buf_len - len; 83 if (delta > 0) { 84 body_.append(data + len, delta); 85 } 86 87 request_headers_received_ = true; 88 return len; 89 } 90 91 void QuicSpdyServerStream::SendResponse() { 92 // Find response in cache. If not found, send error response. 93 const QuicInMemoryCache::Response* response = 94 QuicInMemoryCache::GetInstance()->GetResponse(headers_); 95 if (response == NULL) { 96 SendErrorResponse(); 97 return; 98 } 99 100 DLOG(INFO) << "Sending response for stream " << id(); 101 SendHeadersAndBody(response->headers(), response->body()); 102 } 103 104 void QuicSpdyServerStream::SendErrorResponse() { 105 DLOG(INFO) << "Sending error response for stream " << id(); 106 BalsaHeaders headers; 107 headers.SetResponseFirstlineFromStringPieces( 108 "HTTP/1.1", "500", "Server Error"); 109 headers.ReplaceOrAppendHeader("content-length", "3"); 110 SendHeadersAndBody(headers, "bad"); 111 } 112 113 void QuicSpdyServerStream:: SendHeadersAndBody( 114 const BalsaHeaders& response_headers, 115 StringPiece body) { 116 // We only support SPDY and HTTP, and neither handles bidirectional streaming. 117 if (!read_side_closed()) { 118 CloseReadSide(); 119 } 120 121 SpdyHeaderBlock header_block = 122 SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers); 123 124 string headers_string = 125 session()->compressor()->CompressHeaders(header_block); 126 WriteOrBufferData(headers_string, body.empty()); 127 128 if (!body.empty()) { 129 WriteOrBufferData(body, true); 130 } 131 } 132 133 } // namespace tools 134 } // namespace net 135