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

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

Issue 1570343005: relnote: Implement server push methods in QuicSimpleServerSession. Only modify toy Quic server, not… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@0044_CL_111708360
Patch Set: rebase to chain after fix Created 4 years, 11 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_simple_server_session.h" 5 #include "net/tools/quic/quic_simple_server_session.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/stl_util.h"
8 #include "net/quic/proto/cached_network_parameters.pb.h" 9 #include "net/quic/proto/cached_network_parameters.pb.h"
9 #include "net/quic/quic_connection.h" 10 #include "net/quic/quic_connection.h"
10 #include "net/quic/quic_flags.h" 11 #include "net/quic/quic_flags.h"
11 #include "net/quic/quic_spdy_session.h" 12 #include "net/quic/quic_spdy_session.h"
12 #include "net/quic/reliable_quic_stream.h" 13 #include "net/quic/reliable_quic_stream.h"
13 #include "net/tools/quic/quic_simple_server_stream.h" 14 #include "net/tools/quic/quic_simple_server_stream.h"
15 #include "url/gurl.h"
14 16
15 namespace net { 17 namespace net {
16 namespace tools { 18 namespace tools {
17 19
18 QuicSimpleServerSession::QuicSimpleServerSession( 20 QuicSimpleServerSession::QuicSimpleServerSession(
19 const QuicConfig& config, 21 const QuicConfig& config,
20 QuicConnection* connection, 22 QuicConnection* connection,
21 QuicServerSessionVisitor* visitor, 23 QuicServerSessionVisitor* visitor,
22 const QuicCryptoServerConfig* crypto_config) 24 const QuicCryptoServerConfig* crypto_config)
23 : QuicServerSessionBase(config, connection, visitor, crypto_config) {} 25 : QuicServerSessionBase(config, connection, visitor, crypto_config),
26 highest_promised_stream_id_(0) {}
24 27
25 QuicSimpleServerSession::~QuicSimpleServerSession() {} 28 QuicSimpleServerSession::~QuicSimpleServerSession() {}
26 29
27 QuicCryptoServerStreamBase* 30 QuicCryptoServerStreamBase*
28 QuicSimpleServerSession::CreateQuicCryptoServerStream( 31 QuicSimpleServerSession::CreateQuicCryptoServerStream(
29 const QuicCryptoServerConfig* crypto_config) { 32 const QuicCryptoServerConfig* crypto_config) {
30 return new QuicCryptoServerStream(crypto_config, this); 33 return new QuicCryptoServerStream(crypto_config, this);
31 } 34 }
32 35
36 void QuicSimpleServerSession::StreamDraining(QuicStreamId id) {
37 QuicSpdySession::StreamDraining(id);
38 if (!IsIncomingStream(id)) {
39 HandlePromisedPushRequests();
40 }
41 }
42
43 void QuicSimpleServerSession::OnStreamFrame(const QuicStreamFrame& frame) {
44 if (!IsIncomingStream(frame.stream_id)) {
45 LOG(WARNING) << "Client shouldn't send data on server push stream";
46 connection()->SendConnectionCloseWithDetails(
47 QUIC_INVALID_STREAM_ID, "Client sent data on server push stream");
48 return;
49 }
50 QuicSpdySession::OnStreamFrame(frame);
51 }
52
53 void QuicSimpleServerSession::PromisePushResources(
54 const string& request_url,
55 const list<QuicInMemoryCache::ServerPushInfo>& resources,
56 QuicStreamId original_stream_id,
57 const SpdyHeaderBlock& original_request_headers) {
58 for (QuicInMemoryCache::ServerPushInfo resource : resources) {
59 SpdyHeaderBlock headers = SynthesizePushRequestHeaders(
60 request_url, resource, original_request_headers);
61 highest_promised_stream_id_ += 2;
62 SendPushPromise(original_stream_id, highest_promised_stream_id_, headers);
63 promised_streams_.push_back(PromisedStreamInfo(
64 headers, highest_promised_stream_id_, resource.priority));
65 }
66
67 // Procese promised push request as many as possible.
68 HandlePromisedPushRequests();
69 }
70
33 QuicSpdyStream* QuicSimpleServerSession::CreateIncomingDynamicStream( 71 QuicSpdyStream* QuicSimpleServerSession::CreateIncomingDynamicStream(
34 QuicStreamId id) { 72 QuicStreamId id) {
35 if (!ShouldCreateIncomingDynamicStream(id)) { 73 if (!ShouldCreateIncomingDynamicStream(id)) {
36 return nullptr; 74 return nullptr;
37 } 75 }
38 76
39 return new QuicSimpleServerStream(id, this); 77 return new QuicSimpleServerStream(id, this);
40 } 78 }
41 79
42 QuicSimpleServerStream* QuicSimpleServerSession::CreateOutgoingDynamicStream( 80 QuicSimpleServerStream* QuicSimpleServerSession::CreateOutgoingDynamicStream(
43 SpdyPriority priority) { 81 SpdyPriority priority) {
44 if (!ShouldCreateOutgoingDynamicStream()) { 82 if (!ShouldCreateOutgoingDynamicStream()) {
45 return nullptr; 83 return nullptr;
46 } 84 }
47 85
48 QuicSimpleServerStream* stream = 86 QuicSimpleServerStream* stream =
49 new QuicSimpleServerStream(GetNextOutgoingStreamId(), this); 87 new QuicSimpleServerStream(GetNextOutgoingStreamId(), this);
50 stream->SetPriority(priority); 88 stream->SetPriority(priority);
51 ActivateStream(stream); 89 ActivateStream(stream);
52 return stream; 90 return stream;
53 } 91 }
54 92
93 void QuicSimpleServerSession::CloseStreamInner(QuicStreamId stream_id,
94 bool locally_reset) {
95 QuicSpdySession::CloseStreamInner(stream_id, locally_reset);
96 HandlePromisedPushRequests();
97 }
98
99 void QuicSimpleServerSession::HandleFrameOnNonexistentOutgoingStream(
100 QuicStreamId stream_id) {
101 // If this stream is a promised but not created stream (stream_id within the
102 // range of next_outgoing_stream_id_ and highes_promised_stream_id_),
103 // connection shouldn't be closed.
104 // Otherwise behave in the same way as base class.
105 if (stream_id > highest_promised_stream_id_) {
106 QuicSession::HandleFrameOnNonexistentOutgoingStream(stream_id);
107 }
108 }
109
110 void QuicSimpleServerSession::HandleRstOnValidNonexistentStream(
111 const QuicRstStreamFrame& frame) {
112 QuicSession::HandleRstOnValidNonexistentStream(frame);
113 if (!IsClosedStream(frame.stream_id)) {
114 // If a nonexistent stream is not a closed stream and still valid, it must
115 // be a locally preserved stream. Resetting this kind of stream means
116 // cancelling the promised server push.
117 // Since PromisedStreamInfo are queued in sequence, the corresponding
118 // index for it in promised_streams_ can be calculated.
119 DCHECK(frame.stream_id >= next_outgoing_stream_id());
120 size_t index = (frame.stream_id - next_outgoing_stream_id()) / 2;
121 DCHECK(index <= promised_streams_.size());
122 promised_streams_[index].is_cancelled = true;
123 connection()->SendRstStream(frame.stream_id, QUIC_RST_ACKNOWLEDGEMENT, 0);
124 }
125 }
126
127 SpdyHeaderBlock QuicSimpleServerSession::SynthesizePushRequestHeaders(
128 string request_url,
129 QuicInMemoryCache::ServerPushInfo resource,
130 const SpdyHeaderBlock& original_request_headers) {
131 GURL push_request_url = resource.request_url;
132 string path = push_request_url.path();
133
134 SpdyHeaderBlock spdy_headers = original_request_headers;
135 // :authority could be different from original request.
136 spdy_headers.ReplaceOrAppendHeader(":authority", push_request_url.host());
137 spdy_headers.ReplaceOrAppendHeader(":path", path);
138 // Push request always use GET.
139 spdy_headers.ReplaceOrAppendHeader(":method", "GET");
140 spdy_headers.ReplaceOrAppendHeader("referer", request_url);
141 spdy_headers.ReplaceOrAppendHeader(":scheme", push_request_url.scheme());
142 // It is not possible to push a response to a request that includes a request
143 // body.
144 spdy_headers.ReplaceOrAppendHeader("content-length", "0");
145 // Remove "host" field as push request is a directly generated HTTP2 request
146 // which should use ":authority" instead of "host".
147 spdy_headers.erase("host");
148 return spdy_headers;
149 }
150
151 void QuicSimpleServerSession::SendPushPromise(
152 QuicStreamId original_stream_id,
153 QuicStreamId promised_stream_id,
154 const SpdyHeaderBlock& headers) {
155 DVLOG(1) << "stream " << original_stream_id
156 << " send PUSH_PROMISE for promised stream " << promised_stream_id;
157 headers_stream()->WritePushPromise(original_stream_id, promised_stream_id,
158 headers, nullptr);
159 }
160
161 void QuicSimpleServerSession::HandlePromisedPushRequests() {
162 while (!promised_streams_.empty() && ShouldCreateOutgoingDynamicStream()) {
163 const PromisedStreamInfo& promised_info = promised_streams_.front();
164 DCHECK_EQ(next_outgoing_stream_id(), promised_info.stream_id);
165
166 if (promised_info.is_cancelled) {
167 // This stream has been reset by client. Skip this stream id.
168 promised_streams_.pop_front();
169 GetNextOutgoingStreamId();
170 return;
171 }
172
173 QuicSimpleServerStream* promised_stream =
174 static_cast<QuicSimpleServerStream*>(
175 CreateOutgoingDynamicStream(promised_info.priority));
176 DCHECK(promised_stream != nullptr);
177 DCHECK_EQ(promised_info.stream_id, promised_stream->id());
178 DVLOG(1) << "created server push stream " << promised_stream->id();
179
180 promised_stream->PushResponse(promised_info.request_headers);
181
182 promised_streams_.pop_front();
183 }
184 }
185
55 } // namespace tools 186 } // namespace tools
56 } // namespace net 187 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_simple_server_session.h ('k') | net/tools/quic/quic_simple_server_session_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698