| OLD | NEW |
| 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_simple_server_stream.h" | 5 #include "net/tools/quic/quic_simple_server_stream.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_piece.h" | 10 #include "base/strings/string_piece.h" |
| 11 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
| 12 #include "net/quic/quic_bug_tracker.h" | 12 #include "net/quic/quic_bug_tracker.h" |
| 13 #include "net/quic/quic_flags.h" | 13 #include "net/quic/quic_flags.h" |
| 14 #include "net/quic/quic_spdy_stream.h" | 14 #include "net/quic/quic_spdy_stream.h" |
| 15 #include "net/quic/spdy_utils.h" | 15 #include "net/quic/spdy_utils.h" |
| 16 #include "net/spdy/spdy_protocol.h" | 16 #include "net/spdy/spdy_protocol.h" |
| 17 #include "net/tools/quic/quic_in_memory_cache.h" | 17 #include "net/tools/quic/quic_in_memory_cache.h" |
| 18 #include "net/tools/quic/quic_simple_server_session.h" | 18 #include "net/tools/quic/quic_simple_server_session.h" |
| 19 | 19 |
| 20 using base::StringPiece; | 20 using base::StringPiece; |
| 21 using base::StringToInt; | 21 using base::StringToInt; |
| 22 using std::string; | 22 using std::string; |
| 23 | 23 |
| 24 namespace net { | 24 namespace net { |
| 25 | 25 |
| 26 QuicSimpleServerStream::QuicSimpleServerStream(QuicStreamId id, | 26 QuicSimpleServerStream::QuicSimpleServerStream(QuicStreamId id, |
| 27 QuicSpdySession* session) | 27 QuicSpdySession* session) |
| 28 : QuicSpdyStream(id, session), content_length_(-1) {} | 28 : QuicSpdyStream(id, session), |
| 29 next_state_(INIT), |
| 30 content_length_(-1), |
| 31 body_chunks_consumed_(0) {} |
| 29 | 32 |
| 30 QuicSimpleServerStream::~QuicSimpleServerStream() {} | 33 QuicSimpleServerStream::~QuicSimpleServerStream() {} |
| 31 | 34 |
| 32 void QuicSimpleServerStream::OnInitialHeadersComplete(bool fin, | 35 void QuicSimpleServerStream::OnInitialHeadersComplete(bool fin, |
| 33 size_t frame_len) { | 36 size_t frame_len) { |
| 34 QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len); | 37 QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len); |
| 35 if (!SpdyUtils::ParseHeaders(decompressed_headers().data(), | 38 if (!SpdyUtils::ParseHeaders(decompressed_headers().data(), |
| 36 decompressed_headers().length(), | 39 decompressed_headers().length(), |
| 37 &content_length_, &request_headers_)) { | 40 &content_length_, &request_headers_)) { |
| 38 DVLOG(1) << "Invalid headers"; | 41 DVLOG(1) << "Invalid headers"; |
| 39 SendErrorResponse(); | 42 SendErrorResponse(); |
| 40 } | 43 } |
| 44 |
| 45 const QuicInMemoryCache::Response* response = |
| 46 QuicInMemoryCache::GetInstance()->GetResponse( |
| 47 request_headers_[":authority"], request_headers_[":path"]); |
| 48 if (response != nullptr) { |
| 49 response_.set_response_type(response->response_type()); |
| 50 } |
| 51 |
| 41 MarkHeadersConsumed(decompressed_headers().length()); | 52 MarkHeadersConsumed(decompressed_headers().length()); |
| 42 } | 53 } |
| 43 | 54 |
| 44 void QuicSimpleServerStream::OnTrailingHeadersComplete(bool fin, | 55 void QuicSimpleServerStream::OnTrailingHeadersComplete(bool fin, |
| 45 size_t frame_len) { | 56 size_t frame_len) { |
| 46 QUIC_BUG << "Server does not support receiving Trailers."; | 57 QUIC_BUG << "Server does not support receiving Trailers."; |
| 47 SendErrorResponse(); | 58 SendErrorResponse(); |
| 48 } | 59 } |
| 49 | 60 |
| 50 void QuicSimpleServerStream::OnDataAvailable() { | 61 void QuicSimpleServerStream::OnDataAvailable() { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 61 static_cast<int>(body_.size()) > content_length_) { | 72 static_cast<int>(body_.size()) > content_length_) { |
| 62 DVLOG(1) << "Body size (" << body_.size() << ") > content length (" | 73 DVLOG(1) << "Body size (" << body_.size() << ") > content length (" |
| 63 << content_length_ << ")."; | 74 << content_length_ << ")."; |
| 64 SendErrorResponse(); | 75 SendErrorResponse(); |
| 65 return; | 76 return; |
| 66 } | 77 } |
| 67 MarkConsumed(iov.iov_len); | 78 MarkConsumed(iov.iov_len); |
| 68 } | 79 } |
| 69 if (!sequencer()->IsClosed()) { | 80 if (!sequencer()->IsClosed()) { |
| 70 sequencer()->SetUnblocked(); | 81 sequencer()->SetUnblocked(); |
| 82 if (response_.response_type() == QuicInMemoryCache::BIDIRECTIONAL) { |
| 83 // This will continue send multipart body or trailers. |
| 84 if (next_state_ != NONE) |
| 85 DoLoop(); |
| 86 } |
| 71 return; | 87 return; |
| 72 } | 88 } |
| 73 | 89 |
| 74 // If the sequencer is closed, then all the body, including the fin, has been | 90 // If the sequencer is closed, then all the body, including the fin, has been |
| 75 // consumed. | 91 // consumed. |
| 76 OnFinRead(); | 92 OnFinRead(); |
| 77 | 93 |
| 78 if (write_side_closed() || fin_buffered()) { | 94 if (write_side_closed() || fin_buffered()) { |
| 79 return; | 95 return; |
| 80 } | 96 } |
| 81 | 97 |
| 82 if (request_headers_.empty()) { | 98 if (request_headers_.empty()) { |
| 83 DVLOG(1) << "Request headers empty."; | 99 DVLOG(1) << "Request headers empty."; |
| 84 SendErrorResponse(); | 100 SendErrorResponse(); |
| 85 return; | 101 return; |
| 86 } | 102 } |
| 87 | 103 |
| 88 if (content_length_ > 0 && | 104 if (content_length_ > 0 && |
| 89 content_length_ != static_cast<int>(body_.size())) { | 105 content_length_ != static_cast<int>(body_.size())) { |
| 90 DVLOG(1) << "Content length (" << content_length_ << ") != body size (" | 106 DVLOG(1) << "Content length (" << content_length_ << ") != body size (" |
| 91 << body_.size() << ")."; | 107 << body_.size() << ")."; |
| 92 SendErrorResponse(); | 108 SendErrorResponse(); |
| 93 return; | 109 return; |
| 94 } | 110 } |
| 95 | 111 |
| 96 SendResponse(); | 112 if (next_state_ != NONE) |
| 113 DoLoop(); |
| 97 } | 114 } |
| 98 | 115 |
| 99 void QuicSimpleServerStream::PushResponse( | 116 void QuicSimpleServerStream::PushResponse( |
| 100 SpdyHeaderBlock push_request_headers) { | 117 SpdyHeaderBlock push_request_headers) { |
| 101 if (id() % 2 != 0) { | 118 if (id() % 2 != 0) { |
| 102 QUIC_BUG << "Client initiated stream shouldn't be used as promised stream."; | 119 QUIC_BUG << "Client initiated stream shouldn't be used as promised stream."; |
| 103 return; | 120 return; |
| 104 } | 121 } |
| 105 // Change the stream state to emulate a client request. | 122 // Change the stream state to emulate a client request. |
| 106 request_headers_ = push_request_headers; | 123 request_headers_ = push_request_headers; |
| 107 content_length_ = 0; | 124 content_length_ = 0; |
| 108 DVLOG(1) << "Stream " << id() << ": Ready to receive server push response."; | 125 DVLOG(1) << "Stream " << id() << ": Ready to receive server push response."; |
| 109 | 126 |
| 110 // Set as if stream decompresed the headers and received fin. | 127 // Set as if stream decompresed the headers and received fin. |
| 111 QuicSpdyStream::OnInitialHeadersComplete(/*fin=*/true, 0); | 128 QuicSpdyStream::OnInitialHeadersComplete(/*fin=*/true, 0); |
| 112 } | 129 } |
| 113 | 130 |
| 114 void QuicSimpleServerStream::SendResponse() { | 131 void QuicSimpleServerStream::SendNotFoundResponse() { |
| 132 DVLOG(1) << "Sending not found response for stream " << id(); |
| 133 |
| 134 SpdyHeaderBlock response_headers; |
| 135 response_headers[":status"] = "404"; |
| 136 response_headers["content-length"] = |
| 137 base::IntToString(strlen(kNotFoundResponseBody)); |
| 138 response_.set_response_type(QuicInMemoryCache::REGULAR_RESPONSE); |
| 139 response_.set_headers(response_headers); |
| 140 response_.set_body(kNotFoundResponseBody); |
| 141 |
| 142 next_state_ = SEND_HEADERS; |
| 143 DoLoop(); |
| 144 } |
| 145 |
| 146 void QuicSimpleServerStream::SendErrorResponse() { |
| 147 DVLOG(1) << "Sending error response for stream " << id(); |
| 148 |
| 149 SpdyHeaderBlock response_headers; |
| 150 response_headers[":status"] = "500"; |
| 151 response_headers["content-length"] = |
| 152 base::UintToString(strlen(kErrorResponseBody)); |
| 153 response_.set_response_type(QuicInMemoryCache::REGULAR_RESPONSE); |
| 154 response_.set_headers(response_headers); |
| 155 response_.set_body(kErrorResponseBody); |
| 156 |
| 157 next_state_ = SEND_HEADERS; |
| 158 DoLoop(); |
| 159 } |
| 160 |
| 161 void QuicSimpleServerStream::DoLoop() { |
| 162 DCHECK_NE(NONE, next_state_); |
| 163 do { |
| 164 State state = next_state_; |
| 165 next_state_ = NONE; |
| 166 switch (state) { |
| 167 case INIT: |
| 168 Init(); |
| 169 break; |
| 170 case SEND_HEADERS: |
| 171 SendHeaders(); |
| 172 break; |
| 173 case SEND_BODY: |
| 174 SendBody(); |
| 175 break; |
| 176 case SEND_TRAILERS: |
| 177 SendTrailers(); |
| 178 break; |
| 179 default: |
| 180 NOTREACHED(); |
| 181 } |
| 182 } while (next_state_ != NONE && |
| 183 (sequencer()->IsClosed() || |
| 184 response_.response_type() != QuicInMemoryCache::BIDIRECTIONAL)); |
| 185 } |
| 186 |
| 187 void QuicSimpleServerStream::Init() { |
| 115 if (!ContainsKey(request_headers_, ":authority") || | 188 if (!ContainsKey(request_headers_, ":authority") || |
| 116 !ContainsKey(request_headers_, ":path")) { | 189 !ContainsKey(request_headers_, ":path")) { |
| 117 DVLOG(1) << "Request headers do not contain :authority or :path."; | 190 DVLOG(1) << "Request headers do not contain :authority or :path."; |
| 118 SendErrorResponse(); | 191 SendErrorResponse(); |
| 119 return; | 192 return; |
| 120 } | 193 } |
| 121 | 194 |
| 122 // Find response in cache. If not found, send error response. | 195 // Find response in cache. If not found, send error response. |
| 123 const QuicInMemoryCache::Response* response = | 196 const QuicInMemoryCache::Response* response = |
| 124 QuicInMemoryCache::GetInstance()->GetResponse( | 197 QuicInMemoryCache::GetInstance()->GetResponse( |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 << id(); | 252 << id(); |
| 180 | 253 |
| 181 if (!resources.empty()) { | 254 if (!resources.empty()) { |
| 182 QuicSimpleServerSession* session = | 255 QuicSimpleServerSession* session = |
| 183 static_cast<QuicSimpleServerSession*>(spdy_session()); | 256 static_cast<QuicSimpleServerSession*>(spdy_session()); |
| 184 session->PromisePushResources(request_url, resources, id(), | 257 session->PromisePushResources(request_url, resources, id(), |
| 185 request_headers_); | 258 request_headers_); |
| 186 } | 259 } |
| 187 | 260 |
| 188 DVLOG(1) << "Sending response for stream " << id(); | 261 DVLOG(1) << "Sending response for stream " << id(); |
| 189 SendHeadersAndBodyAndTrailers(response->headers(), response->body(), | 262 response_.set_response_type(response->response_type()); |
| 190 response->trailers()); | 263 response_.set_headers(response->headers()); |
| 264 response_.set_body(response->body()); |
| 265 response_.set_trailers(response->trailers()); |
| 266 response_.SetBodyChunks(response->body_chunks()); |
| 267 next_state_ = SEND_HEADERS; |
| 191 } | 268 } |
| 192 | 269 |
| 193 void QuicSimpleServerStream::SendNotFoundResponse() { | 270 void QuicSimpleServerStream::SendHeaders() { |
| 194 DVLOG(1) << "Sending not found response for stream " << id(); | 271 // Stop reading if this response is not bidirectional. |
| 195 SpdyHeaderBlock headers; | 272 if (response_.response_type() != QuicInMemoryCache::BIDIRECTIONAL) { |
| 196 headers[":status"] = "404"; | 273 if (!reading_stopped()) { |
| 197 headers["content-length"] = base::IntToString(strlen(kNotFoundResponseBody)); | 274 StopReading(); |
| 198 SendHeadersAndBody(headers, kNotFoundResponseBody); | 275 } |
| 199 } | |
| 200 | |
| 201 void QuicSimpleServerStream::SendErrorResponse() { | |
| 202 DVLOG(1) << "Sending error response for stream " << id(); | |
| 203 SpdyHeaderBlock headers; | |
| 204 headers[":status"] = "500"; | |
| 205 headers["content-length"] = base::UintToString(strlen(kErrorResponseBody)); | |
| 206 SendHeadersAndBody(headers, kErrorResponseBody); | |
| 207 } | |
| 208 | |
| 209 void QuicSimpleServerStream::SendHeadersAndBody( | |
| 210 const SpdyHeaderBlock& response_headers, | |
| 211 StringPiece body) { | |
| 212 SendHeadersAndBodyAndTrailers(response_headers, body, SpdyHeaderBlock()); | |
| 213 } | |
| 214 | |
| 215 void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers( | |
| 216 const SpdyHeaderBlock& response_headers, | |
| 217 StringPiece body, | |
| 218 const SpdyHeaderBlock& response_trailers) { | |
| 219 // This server only supports SPDY and HTTP, and neither handles bidirectional | |
| 220 // streaming. | |
| 221 if (!reading_stopped()) { | |
| 222 StopReading(); | |
| 223 } | 276 } |
| 224 | |
| 225 // Send the headers, with a FIN if there's nothing else to send. | 277 // Send the headers, with a FIN if there's nothing else to send. |
| 226 bool send_fin = (body.empty() && response_trailers.empty()); | 278 bool send_fin = |
| 279 (response_.body().empty() && response_.body_chunks().empty() && |
| 280 response_.trailers().empty()); |
| 227 DVLOG(1) << "Writing headers (fin = " << send_fin | 281 DVLOG(1) << "Writing headers (fin = " << send_fin |
| 228 << ") : " << response_headers.DebugString(); | 282 << ") : " << response_.headers().DebugString(); |
| 229 WriteHeaders(response_headers, send_fin, nullptr); | 283 WriteHeaders(response_.headers(), send_fin, nullptr); |
| 230 if (send_fin) { | 284 if (send_fin) { |
| 231 // Nothing else to send. | 285 // Nothing else to send. |
| 232 return; | 286 return; |
| 233 } | 287 } |
| 288 next_state_ = SEND_BODY; |
| 289 } |
| 234 | 290 |
| 235 // Send the body, with a FIN if there's nothing else to send. | 291 void QuicSimpleServerStream::SendBody() { |
| 236 send_fin = response_trailers.empty(); | 292 if (response_.response_type() == QuicInMemoryCache::BIDIRECTIONAL) { |
| 237 DVLOG(1) << "Writing body (fin = " << send_fin | 293 if (response_.body_chunks().size() > body_chunks_consumed_) { |
| 238 << ") with size: " << body.size(); | 294 WriteOrBufferData( |
| 239 WriteOrBufferData(body, send_fin, nullptr); | 295 response_.body_chunks().at(body_chunks_consumed_), |
| 240 if (send_fin) { | 296 response_.trailers().empty() && |
| 241 // Nothing else to send. | 297 body_chunks_consumed_ + 1 == response_.body_chunks().size(), |
| 242 return; | 298 nullptr); |
| 299 body_chunks_consumed_++; |
| 300 next_state_ = SEND_BODY; |
| 301 } else if (response_.body_chunks().size() == body_chunks_consumed_) { |
| 302 if (response_.trailers().empty()) |
| 303 return; |
| 304 next_state_ = SEND_TRAILERS; |
| 305 } |
| 306 } else { |
| 307 // Send the body, with a FIN if there's nothing else to send. |
| 308 bool send_fin = response_.trailers().empty(); |
| 309 DVLOG(1) << "Writing body (fin = " << send_fin |
| 310 << ") with size: " << response_.body().size(); |
| 311 WriteOrBufferData(response_.body(), send_fin, nullptr); |
| 312 if (send_fin) { |
| 313 // Nothing else to send. |
| 314 return; |
| 315 } |
| 316 next_state_ = SEND_TRAILERS; |
| 243 } | 317 } |
| 318 } |
| 244 | 319 |
| 320 void QuicSimpleServerStream::SendTrailers() { |
| 245 // Send the trailers. A FIN is always sent with trailers. | 321 // Send the trailers. A FIN is always sent with trailers. |
| 246 DVLOG(1) << "Writing trailers (fin = true): " | 322 DVLOG(1) << "Writing trailers (fin = true): " |
| 247 << response_trailers.DebugString(); | 323 << response_.trailers().DebugString(); |
| 248 WriteTrailers(response_trailers, nullptr); | 324 WriteTrailers(response_.trailers(), nullptr); |
| 325 next_state_ = NONE; |
| 249 } | 326 } |
| 250 | 327 |
| 251 const char* const QuicSimpleServerStream::kErrorResponseBody = "bad"; | 328 const char* const QuicSimpleServerStream::kErrorResponseBody = "bad"; |
| 252 const char* const QuicSimpleServerStream::kNotFoundResponseBody = | 329 const char* const QuicSimpleServerStream::kNotFoundResponseBody = |
| 253 "file not found"; | 330 "file not found"; |
| 254 | 331 |
| 255 } // namespace net | 332 } // namespace net |
| OLD | NEW |