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 "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" 15 16 using base::StringPiece; 17 using std::string; 18 19 namespace net { 20 21 static const size_t kHeaderBufInitialSize = 4096; 22 23 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, 24 QuicSession* session) 25 : QuicDataStream(id, session), 26 read_buf_(new GrowableIOBuffer()), 27 request_headers_received_(false) { 28 read_buf_->SetCapacity(kHeaderBufInitialSize); 29 } 30 31 QuicSpdyServerStream::~QuicSpdyServerStream() { 32 } 33 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; 37 return 0; 38 } 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); 44 } 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(); 50 } else { 51 body_.append(data, data_len); 52 } 53 return data_len; 54 } 55 56 void QuicSpdyServerStream::OnFinRead() { 57 ReliableQuicStream::OnFinRead(); 58 if (write_side_closed() || fin_buffered()) { 59 return; 60 } 61 62 if (!request_headers_received_) { 63 SendErrorResponse(); // We're not done reading headers. 64 return; 65 } 66 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 73 return; 74 } 75 76 SendResponse(); 77 } 78 79 // Try parsing the request headers. If successful, sets 80 // request_headers_received_. If not successful, it can just be tried again once 81 // there's more data. 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_); 87 if (len == 0) { 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().) 90 return; 91 } 92 93 // Headers received and parsed: extract the request URL. 94 request_url_ = GetUrlFromHeaderBlock(headers_, 95 kDefaultSpdyMajorVersion, 96 false); 97 if (!request_url_.is_valid()) { 98 SendErrorResponse(); 99 return; 100 } 101 102 // Add any data past the headers to the request body. 103 size_t delta = read_buf_len - len; 104 if (delta > 0) { 105 body_.append(data + len, delta); 106 } 107 108 request_headers_received_ = true; 109 } 110 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) { 116 SendErrorResponse(); 117 return; 118 } 119 120 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) { 121 DVLOG(1) << "Special response: closing connection."; 122 CloseConnection(QUIC_NO_ERROR); 123 return; 124 } 125 126 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) { 127 DVLOG(1) << "Special response: ignoring request."; 128 return; 129 } 130 131 DVLOG(1) << "Sending response for stream " << id(); 132 SendHeadersAndBody(response->headers(), response->body()); 133 } 134 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.get(), "bad"); 141 } 142 143 void QuicSpdyServerStream::SendHeadersAndBody( 144 const HttpResponseHeaders& response_headers, 145 StringPiece body) { 146 // We only support SPDY and HTTP, and neither handles bidirectional streaming. 147 if (!read_side_closed()) { 148 CloseReadSide(); 149 } 150 151 SpdyHeaderBlock header_block; 152 CreateSpdyHeadersFromHttpResponse(response_headers, 153 kDefaultSpdyMajorVersion, 154 &header_block); 155 156 WriteHeaders(header_block, body.empty(), NULL); 157 158 if (!body.empty()) { 159 WriteOrBufferData(body, true, NULL); 160 } 161 } 162 163 } // namespace net 164