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

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

Issue 1521993006: Rename QuicSpdyServerStream to QuicSimpleServerStream. No behavior change. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@109918216
Patch Set: correct NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_STREAM_H_ Created 5 years 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
(Empty)
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/logging.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_split.h"
12 #include "net/quic/quic_flags.h"
13 #include "net/quic/quic_spdy_session.h"
14 #include "net/quic/quic_spdy_stream.h"
15 #include "net/quic/spdy_utils.h"
16 #include "net/spdy/spdy_protocol.h"
17 #include "net/tools/quic/quic_in_memory_cache.h"
18
19 using base::StringPiece;
20 using base::StringToInt;
21 using std::string;
22
23 namespace net {
24 namespace tools {
25
26 QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
27 QuicSpdySession* session)
28 : QuicSpdyStream(id, session), content_length_(-1) {}
29
30 QuicSpdyServerStream::~QuicSpdyServerStream() {
31 }
32
33 void QuicSpdyServerStream::OnInitialHeadersComplete(bool fin,
34 size_t frame_len) {
35 QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len);
36 if (!SpdyUtils::ParseHeaders(decompressed_headers().data(),
37 decompressed_headers().length(),
38 &content_length_, &request_headers_)) {
39 DVLOG(1) << "Invalid headers";
40 SendErrorResponse();
41 }
42 MarkHeadersConsumed(decompressed_headers().length());
43 }
44
45 void QuicSpdyServerStream::OnTrailingHeadersComplete(bool fin,
46 size_t frame_len) {
47 LOG(DFATAL) << "Server does not support receiving Trailers.";
48 SendErrorResponse();
49 }
50
51 void QuicSpdyServerStream::OnDataAvailable() {
52 while (HasBytesToRead()) {
53 struct iovec iov;
54 if (GetReadableRegions(&iov, 1) == 0) {
55 // No more data to read.
56 break;
57 }
58 DVLOG(1) << "Processed " << iov.iov_len << " bytes for stream " << id();
59 body_.append(static_cast<char*>(iov.iov_base), iov.iov_len);
60
61 if (content_length_ >= 0 &&
62 static_cast<int>(body_.size()) > content_length_) {
63 DVLOG(1) << "Body size (" << body_.size() << ") > content length ("
64 << content_length_ << ").";
65 SendErrorResponse();
66 return;
67 }
68 MarkConsumed(iov.iov_len);
69 }
70 if (!sequencer()->IsClosed()) {
71 sequencer()->SetUnblocked();
72 return;
73 }
74
75 // If the sequencer is closed, then all the body, including the fin, has been
76 // consumed.
77 OnFinRead();
78
79 if (write_side_closed() || fin_buffered()) {
80 return;
81 }
82
83 if (request_headers_.empty()) {
84 DVLOG(1) << "Request headers empty.";
85 SendErrorResponse();
86 return;
87 }
88
89 if (content_length_ > 0 &&
90 content_length_ != static_cast<int>(body_.size())) {
91 DVLOG(1) << "Content length (" << content_length_ << ") != body size ("
92 << body_.size() << ").";
93 SendErrorResponse();
94 return;
95 }
96
97 SendResponse();
98 }
99
100 void QuicSpdyServerStream::SendResponse() {
101 if (!ContainsKey(request_headers_, ":authority") ||
102 !ContainsKey(request_headers_, ":path")) {
103 DVLOG(1) << "Request headers do not contain :authority or :path.";
104 SendErrorResponse();
105 return;
106 }
107
108 // Find response in cache. If not found, send error response.
109 const QuicInMemoryCache::Response* response =
110 QuicInMemoryCache::GetInstance()->GetResponse(
111 request_headers_[":authority"], request_headers_[":path"]);
112 if (response == nullptr) {
113 DVLOG(1) << "Response not found in cache.";
114 SendErrorResponse();
115 return;
116 }
117
118 if (response->response_type() == QuicInMemoryCache::CLOSE_CONNECTION) {
119 DVLOG(1) << "Special response: closing connection.";
120 CloseConnection(QUIC_NO_ERROR);
121 return;
122 }
123
124 if (response->response_type() == QuicInMemoryCache::IGNORE_REQUEST) {
125 DVLOG(1) << "Special response: ignoring request.";
126 return;
127 }
128
129 // Examing response status, if it was not pure integer as typical h2 response
130 // status, send error response.
131 string request_url = request_headers_[":scheme"].as_string() + "://" +
132 request_headers_[":authority"].as_string() +
133 request_headers_[":path"].as_string();
134 int response_code;
135 SpdyHeaderBlock response_headers = response->headers();
136 if (!base::StringToInt(response_headers[":status"], &response_code)) {
137 DVLOG(1) << "Illegal (non-integer) response :status from cache: "
138 << response_headers[":status"].as_string() << " for request "
139 << request_url;
140 SendErrorResponse();
141 return;
142 }
143
144 if (id() % 2 == 0) {
145 // A server initiated stream is only used for a server push response,
146 // and only 200 and 30X response codes are supported for server push.
147 // This behavior mirrors the HTTP/2 implementation.
148 bool is_redirection = response_code / 100 == 3;
149 if (response_code != 200 && !is_redirection) {
150 LOG(WARNING) << "Response to server push request " << request_url
151 << " result in response code " << response_code;
152 Reset(QUIC_STREAM_CANCELLED);
153 return;
154 }
155 }
156 DVLOG(1) << "Sending response for stream " << id();
157 SendHeadersAndBodyAndTrailers(response->headers(), response->body(),
158 response->trailers());
159 }
160
161 void QuicSpdyServerStream::SendErrorResponse() {
162 DVLOG(1) << "Sending error response for stream " << id();
163 SpdyHeaderBlock headers;
164 headers[":status"] = "500";
165 headers["content-length"] = base::UintToString(strlen(kErrorResponseBody));
166 SendHeadersAndBody(headers, kErrorResponseBody);
167 }
168
169 void QuicSpdyServerStream::SendHeadersAndBody(
170 const SpdyHeaderBlock& response_headers,
171 StringPiece body) {
172 SendHeadersAndBodyAndTrailers(response_headers, body, SpdyHeaderBlock());
173 }
174
175 void QuicSpdyServerStream::SendHeadersAndBodyAndTrailers(
176 const SpdyHeaderBlock& response_headers,
177 StringPiece body,
178 const SpdyHeaderBlock& response_trailers) {
179 // This server only supports SPDY and HTTP, and neither handles bidirectional
180 // streaming.
181 if (!reading_stopped()) {
182 StopReading();
183 }
184
185 // Send the headers, with a FIN if there's nothing else to send.
186 bool send_fin = (body.empty() && response_trailers.empty());
187 DVLOG(1) << "Writing headers (fin = " << send_fin
188 << ") : " << response_headers.DebugString();
189 WriteHeaders(response_headers, send_fin, nullptr);
190 if (send_fin) {
191 // Nothing else to send.
192 return;
193 }
194
195 // Send the body, with a FIN if there's nothing else to send.
196 send_fin = response_trailers.empty();
197 DVLOG(1) << "Writing body (fin = " << send_fin
198 << ") with size: " << body.size();
199 WriteOrBufferData(body, send_fin, nullptr);
200 if (send_fin) {
201 // Nothing else to send.
202 return;
203 }
204
205 // Send the trailers. A FIN is always sent with trailers.
206 DVLOG(1) << "Writing trailers (fin = true): "
207 << response_trailers.DebugString();
208 WriteTrailers(response_trailers, nullptr);
209 }
210
211 const char* const QuicSpdyServerStream::kErrorResponseBody = "bad";
212
213 } // namespace tools
214 } // 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