Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: net/quic/quic_spdy_server_stream.cc

Issue 337093003: QuicServer: Use Chrome's header parsing rather than Balsa (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@quic_server_3
Patch Set: Small cleanup Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/quic_spdy_server_stream.h" 5 #include "net/quic/quic_spdy_server_stream.h"
6 6
7 #include "base/memory/singleton.h" 7 #include "base/memory/singleton.h"
8 #include "base/strings/string_number_conversions.h"
8 #include "net/quic/quic_in_memory_cache.h" 9 #include "net/quic/quic_in_memory_cache.h"
9 #include "net/quic/quic_session.h" 10 #include "net/quic/quic_session.h"
11 #include "net/quic/spdy_utils.h"
wtc 2014/06/26 21:23:17 Nit: put this header in the sorted order.
dmziegler 2014/06/27 01:11:37 It is, actually. (I couldn't have passed presubmit
10 #include "net/spdy/spdy_framer.h" 12 #include "net/spdy/spdy_framer.h"
11 #include "net/tools/quic/spdy_utils.h" 13 #include "net/spdy/spdy_header_block.h"
14 #include "net/spdy/spdy_http_utils.h"
12 15
13 using base::StringPiece; 16 using base::StringPiece;
14 using std::string; 17 using std::string;
15 using net::tools::SpdyUtils;
16 18
17 namespace net { 19 namespace net {
18 20
19 static const size_t kHeaderBufInitialSize = 4096; 21 static const size_t kHeaderBufInitialSize = 4096;
20 22
21 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, 23 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
22 QuicSession* session) 24 QuicSession* session)
23 : QuicDataStream(id, session), 25 : QuicDataStream(id, session),
24 read_buf_(new GrowableIOBuffer()), 26 read_buf_(new GrowableIOBuffer()),
25 request_headers_received_(false) { 27 request_headers_received_(false) {
28 read_buf_->SetCapacity(kHeaderBufInitialSize);
26 } 29 }
27 30
28 QuicSpdyServerStream::~QuicSpdyServerStream() { 31 QuicSpdyServerStream::~QuicSpdyServerStream() {
29 } 32 }
30 33
31 uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) { 34 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 // Are we still reading the request headers.
35 if (!request_headers_received_) { 36 if (!request_headers_received_) {
36 // Grow the read buffer if necessary. 37 // Grow the read buffer if necessary.
37 if (read_buf_->RemainingCapacity() < (int)data_len) { 38 while (read_buf_->RemainingCapacity() < (int)data_len) {
38 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 39 read_buf_->SetCapacity(read_buf_->capacity() * 2);
39 } 40 }
40 memcpy(read_buf_->data(), data, data_len); 41 memcpy(read_buf_->data(), data, data_len);
41 read_buf_->set_offset(read_buf_->offset() + data_len); 42 read_buf_->set_offset(read_buf_->offset() + data_len);
43 // Try parsing the request headers. This will set request_headers_received_
44 // if successful; if not, it will be tried again with more data.
42 ParseRequestHeaders(); 45 ParseRequestHeaders();
43 } else { 46 } else {
44 body_.append(data + total_bytes_processed, 47 body_.append(data, data_len);
45 data_len - total_bytes_processed);
46 } 48 }
47 return data_len; 49 return data_len;
48 } 50 }
49 51
50 void QuicSpdyServerStream::OnFinRead() { 52 void QuicSpdyServerStream::OnFinRead() {
51 ReliableQuicStream::OnFinRead(); 53 ReliableQuicStream::OnFinRead();
52 if (write_side_closed() || fin_buffered()) { 54 if (write_side_closed() || fin_buffered()) {
53 return; 55 return;
54 } 56 }
55 57
56 if (!request_headers_received_) { 58 if (!request_headers_received_) {
57 SendErrorResponse(); // We're not done reading headers. 59 SendErrorResponse(); // We're not done reading headers.
58 } else if ((headers_.content_length_status() == 60 return;
59 BalsaHeadersEnums::VALID_CONTENT_LENGTH) && 61 }
60 body_.size() != headers_.content_length()) { 62
63 SpdyHeaderBlock::const_iterator it = headers_.find("content-length");
64 size_t content_length;
65 if (it != headers_.end() &&
66 (!base::StringToSizeT(it->second, &content_length) ||
67 body_.size() != content_length)) {
61 SendErrorResponse(); // Invalid content length 68 SendErrorResponse(); // Invalid content length
62 } else { 69 return;
63 SendResponse();
64 } 70 }
71
72 SendResponse();
65 } 73 }
66 74
67 size_t QuicSpdyServerStream::ParseRequestHeaders() { 75 // Try parsing the request headers. If successful, sets
76 // request_headers_received_. If not successful, it can just be tried again once
77 // there's more data.
78 void QuicSpdyServerStream::ParseRequestHeaders() {
79 SpdyFramer framer((kDefaultSpdyVersion));
80 char* data = read_buf_->StartOfBuffer();
68 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 81 size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
69 SpdyFramer framer(SPDY3); 82 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_len, &headers_);
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) { 83 if (len == 0) {
75 return -1; 84 // Not enough data yet, presumably. (If we still don't succeed by the end of
85 // the stream, then we'll error above.)
86 return;
76 } 87 }
77 88
78 if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) { 89 // Headers received and parsed: extract the request URL.
90 request_url_ = GetUrlFromHeaderBlock(headers_, kDefaultSpdyVersion, false);
91 if (!request_url_.is_valid()) {
79 SendErrorResponse(); 92 SendErrorResponse();
80 return -1; 93 return;
81 } 94 }
82 95
96 // Add any data past the headers to the request body.
83 size_t delta = read_buf_len - len; 97 size_t delta = read_buf_len - len;
84 if (delta > 0) { 98 if (delta > 0) {
85 body_.append(data + len, delta); 99 body_.append(data + len, delta);
86 } 100 }
87 101
88 request_headers_received_ = true; 102 request_headers_received_ = true;
89 return len;
90 } 103 }
91 104
92 void QuicSpdyServerStream::SendResponse() { 105 void QuicSpdyServerStream::SendResponse() {
93 // Find response in cache. If not found, send error response. 106 // Find response in cache. If not found, send error response.
94 const QuicInMemoryCache::Response* response = 107 const QuicInMemoryCache::Response* response =
95 QuicInMemoryCache::GetInstance()->GetResponse(headers_); 108 QuicInMemoryCache::GetInstance()->GetResponse(request_url_);
96 if (response == NULL) { 109 if (response == NULL) {
97 SendErrorResponse(); 110 SendErrorResponse();
98 return; 111 return;
99 } 112 }
100 113
101 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) { 114 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) {
102 DVLOG(1) << "Special response: closing connection."; 115 DVLOG(1) << "Special response: closing connection.";
103 CloseConnection(QUIC_NO_ERROR); 116 CloseConnection(QUIC_NO_ERROR);
104 return; 117 return;
105 } 118 }
106 119
107 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) { 120 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) {
108 DVLOG(1) << "Special response: ignoring request."; 121 DVLOG(1) << "Special response: ignoring request.";
109 return; 122 return;
110 } 123 }
111 124
112 DVLOG(1) << "Sending response for stream " << id(); 125 DVLOG(1) << "Sending response for stream " << id();
113 SendHeadersAndBody(response->headers(), response->body()); 126 SendHeadersAndBody(response->headers(), response->body());
114 } 127 }
115 128
116 void QuicSpdyServerStream::SendErrorResponse() { 129 void QuicSpdyServerStream::SendErrorResponse() {
117 DVLOG(1) << "Sending error response for stream " << id(); 130 DVLOG(1) << "Sending error response for stream " << id();
118 BalsaHeaders headers; 131 scoped_refptr<HttpResponseHeaders> headers
119 headers.SetResponseFirstlineFromStringPieces( 132 = new HttpResponseHeaders(string("HTTP/1.1 500 Server Error") + '\0' +
120 "HTTP/1.1", "500", "Server Error"); 133 "content-length: 3" + '\0' + '\0');
121 headers.ReplaceOrAppendHeader("content-length", "3"); 134 SendHeadersAndBody(*headers, "bad");
122 SendHeadersAndBody(headers, "bad");
123 } 135 }
124 136
125 void QuicSpdyServerStream::SendHeadersAndBody( 137 void QuicSpdyServerStream::SendHeadersAndBody(
126 const BalsaHeaders& response_headers, 138 const HttpResponseHeaders& response_headers,
127 StringPiece body) { 139 StringPiece body) {
128 // We only support SPDY and HTTP, and neither handles bidirectional streaming. 140 // We only support SPDY and HTTP, and neither handles bidirectional streaming.
129 if (!read_side_closed()) { 141 if (!read_side_closed()) {
130 CloseReadSide(); 142 CloseReadSide();
131 } 143 }
132 144
133 SpdyHeaderBlock header_block = 145 SpdyHeaderBlock header_block;
134 SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers); 146 CreateSpdyHeadersFromHttpResponse(response_headers,
147 kDefaultSpdyVersion,
148 &header_block);
135 149
136 WriteHeaders(header_block, body.empty(), NULL); 150 WriteHeaders(header_block, body.empty(), NULL);
137 151
138 if (!body.empty()) { 152 if (!body.empty()) {
139 WriteOrBufferData(body, true, NULL); 153 WriteOrBufferData(body, true, NULL);
140 } 154 }
141 } 155 }
142 156
143 } // namespace net 157 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698