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

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

Issue 999353005: Land Recent QUIC Changes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: wrap Created 5 years, 9 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 (c) 2012 The Chromium Authors. All rights reserved. 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 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/tools/quic/quic_spdy_server_stream.h" 5 #include "net/tools/quic/quic_spdy_server_stream.h"
6 6
7 #include "base/memory/singleton.h" 7 #include "base/strings/string_number_conversions.h"
8 #include "net/quic/quic_session.h" 8 #include "net/quic/quic_session.h"
9 #include "net/spdy/spdy_framer.h" 9 #include "net/spdy/spdy_framer.h"
10 #include "net/tools/quic/quic_in_memory_cache.h" 10 #include "net/tools/quic/quic_in_memory_cache.h"
11 #include "net/tools/quic/spdy_utils.h" 11 #include "net/tools/quic/spdy_utils.h"
12 #include "url/gurl.h" 12 #include "url/gurl.h"
13 13
14 using base::StringPiece; 14 using base::StringPiece;
15 using base::StringToInt;
15 using std::string; 16 using std::string;
16 17
17 namespace net { 18 namespace net {
18 namespace tools { 19 namespace tools {
19 20
20 static const size_t kHeaderBufInitialSize = 4096;
21
22 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id, 21 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
23 QuicSession* session) 22 QuicSession* session)
24 : QuicDataStream(id, session), 23 : QuicDataStream(id, session),
25 read_buf_(new GrowableIOBuffer()), 24 content_length_(-1) {
26 request_headers_received_(false) {
27 } 25 }
28 26
29 QuicSpdyServerStream::~QuicSpdyServerStream() { 27 QuicSpdyServerStream::~QuicSpdyServerStream() {
30 } 28 }
31 29
32 uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) { 30 uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 data_len) {
33 uint32 total_bytes_processed = 0; 31 if (!headers_decompressed()) {
34 32 // Let the headers data accumulate in the underlying QuicDataStream.
35 // Are we still reading the request headers. 33 return 0;
36 if (!request_headers_received_) { 34 }
37 // Grow the read buffer if necessary. 35 if (request_headers_.empty()) {
38 if (read_buf_->RemainingCapacity() < (int)data_len) { 36 if (!ParseRequestHeaders(data, data_len)) {
39 read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize); 37 // Headers were invalid.
38 SendErrorResponse();
39 return 0;
40 } 40 }
41 memcpy(read_buf_->data(), data, data_len);
42 read_buf_->set_offset(read_buf_->offset() + data_len);
43 ParseRequestHeaders();
44 } else { 41 } else {
45 body_.append(data + total_bytes_processed, 42 body_.append(data, data_len);
46 data_len - total_bytes_processed);
47 } 43 }
44 DCHECK(!request_headers_.empty());
45 if (content_length_ > 0 && static_cast<int>(body_.size()) > content_length_) {
46 SendErrorResponse();
47 return 0;
48 }
49 DVLOG(1) << "Processed " << data_len << " bytes for stream " << id();
48 return data_len; 50 return data_len;
49 } 51 }
50 52
51 void QuicSpdyServerStream::OnFinRead() { 53 void QuicSpdyServerStream::OnFinRead() {
52 ReliableQuicStream::OnFinRead(); 54 ReliableQuicStream::OnFinRead();
53 if (write_side_closed() || fin_buffered()) { 55 if (write_side_closed() || fin_buffered()) {
54 return; 56 return;
55 } 57 }
56 58
57 if (!request_headers_received_) { 59 if (request_headers_.empty()) {
58 SendErrorResponse(); // We're not done reading headers.
59 } else if ((headers_.content_length_status() ==
60 BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
61 body_.size() != headers_.content_length()) {
62 SendErrorResponse(); // Invalid content length
63 } else {
64 SendResponse();
65 }
66 }
67
68 void QuicSpdyServerStream::ParseRequestHeaders() {
69 size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
70 SpdyFramer framer(SPDY3);
71 SpdyHeaderBlock headers;
72 char* data = read_buf_->StartOfBuffer();
73 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(),
74 &headers);
75 if (len == 0) {
76 return;
77 }
78
79 if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) {
80 SendErrorResponse(); 60 SendErrorResponse();
81 return; 61 return;
82 } 62 }
83 63
84 size_t delta = read_buf_len - len; 64 if (content_length_ > 0 &&
85 if (delta > 0) { 65 content_length_ != static_cast<int>(body_.size())) {
86 body_.append(data + len, delta); 66 SendErrorResponse();
67 return;
87 } 68 }
88 69
89 request_headers_received_ = true; 70 SendResponse();
71 }
72
73 bool QuicSpdyServerStream::ParseRequestHeaders(const char* data,
74 uint32 data_len) {
75 DCHECK(headers_decompressed());
76 SpdyFramer framer(SPDY3);
77 size_t len = framer.ParseHeaderBlockInBuffer(data,
78 data_len,
79 &request_headers_);
80 DCHECK_LE(len, data_len);
81 if (len == 0 || request_headers_.empty()) {
82 return false; // Headers were invalid.
83 }
84
85 if (data_len > len) {
86 body_.append(data + len, data_len - len);
87 }
88 if (ContainsKey(request_headers_, "content-length") &&
89 !StringToInt(request_headers_["content-length"], &content_length_)) {
90 return false; // Invalid content-length.
91 }
92 return true;
90 } 93 }
91 94
92 void QuicSpdyServerStream::SendResponse() { 95 void QuicSpdyServerStream::SendResponse() {
93 // Find response in cache. If not found, send error response. 96 if (!ContainsKey(request_headers_, ":host") ||
94 GURL url(headers_.request_uri().as_string()); 97 !ContainsKey(request_headers_, ":path")) {
95 if (!url.is_valid()) {
96 SendErrorResponse(); 98 SendErrorResponse();
97 return; 99 return;
98 } 100 }
101
102 // Find response in cache. If not found, send error response.
99 const QuicInMemoryCache::Response* response = 103 const QuicInMemoryCache::Response* response =
100 QuicInMemoryCache::GetInstance()->GetResponse( 104 QuicInMemoryCache::GetInstance()->GetResponse(
101 url.host(), 105 request_headers_[":host"],
102 url.PathForRequest()); 106 request_headers_[":path"]);
103 if (response == nullptr) { 107 if (response == nullptr) {
104 SendErrorResponse(); 108 SendErrorResponse();
105 return; 109 return;
106 } 110 }
107 111
108 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) { 112 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) {
109 DVLOG(1) << "Special response: closing connection."; 113 DVLOG(1) << "Special response: closing connection.";
110 CloseConnection(QUIC_NO_ERROR); 114 CloseConnection(QUIC_NO_ERROR);
111 return; 115 return;
112 } 116 }
113 117
114 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) { 118 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) {
115 DVLOG(1) << "Special response: ignoring request."; 119 DVLOG(1) << "Special response: ignoring request.";
116 return; 120 return;
117 } 121 }
118 122
119 DVLOG(1) << "Sending response for stream " << id(); 123 DVLOG(1) << "Sending response for stream " << id();
120 SendHeadersAndBody(response->headers(), response->body()); 124 SendHeadersAndBody(response->headers(), response->body());
121 } 125 }
122 126
123 void QuicSpdyServerStream::SendErrorResponse() { 127 void QuicSpdyServerStream::SendErrorResponse() {
124 DVLOG(1) << "Sending error response for stream " << id(); 128 DVLOG(1) << "Sending error response for stream " << id();
125 BalsaHeaders headers; 129 SpdyHeaderBlock headers;
126 headers.SetResponseFirstlineFromStringPieces( 130 headers[":version"] = "HTTP/1.1";
127 "HTTP/1.1", "500", "Server Error"); 131 headers[":status"] = "500 Server Error";
128 headers.ReplaceOrAppendHeader("content-length", "3"); 132 headers["content-length"] = "3";
129 SendHeadersAndBody(headers, "bad"); 133 SendHeadersAndBody(headers, "bad");
130 } 134 }
131 135
132 void QuicSpdyServerStream::SendHeadersAndBody( 136 void QuicSpdyServerStream::SendHeadersAndBody(
133 const BalsaHeaders& response_headers, 137 const SpdyHeaderBlock& response_headers,
134 StringPiece body) { 138 StringPiece body) {
135 // We only support SPDY and HTTP, and neither handles bidirectional streaming. 139 // We only support SPDY and HTTP, and neither handles bidirectional streaming.
136 if (!read_side_closed()) { 140 if (!read_side_closed()) {
137 CloseReadSide(); 141 CloseReadSide();
138 } 142 }
139 143
140 SpdyHeaderBlock header_block = 144 WriteHeaders(response_headers, body.empty(), nullptr);
141 SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers);
142
143 WriteHeaders(header_block, body.empty(), nullptr);
144 145
145 if (!body.empty()) { 146 if (!body.empty()) {
146 WriteOrBufferData(body, true, nullptr); 147 WriteOrBufferData(body, true, nullptr);
147 } 148 }
148 } 149 }
149 150
150 } // namespace tools 151 } // namespace tools
151 } // namespace net 152 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_spdy_server_stream.h ('k') | net/tools/quic/quic_spdy_server_stream_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698