Index: net/tools/quic/quic_simple_server_session.h |
diff --git a/net/tools/quic/quic_simple_server_session.h b/net/tools/quic/quic_simple_server_session.h |
index 12d2b0d4250435a0e6911a3aaaf3b917e1720c33..d9b2901c4bccd7fb123e4402f93d777273187c52 100644 |
--- a/net/tools/quic/quic_simple_server_session.h |
+++ b/net/tools/quic/quic_simple_server_session.h |
@@ -19,6 +19,7 @@ |
#include "net/quic/quic_crypto_server_stream.h" |
#include "net/quic/quic_protocol.h" |
#include "net/quic/quic_spdy_session.h" |
+#include "net/tools/quic/quic_in_memory_cache.h" |
#include "net/tools/quic/quic_server_session_base.h" |
#include "net/tools/quic/quic_simple_server_stream.h" |
@@ -38,6 +39,24 @@ class QuicSimpleServerSessionPeer; |
class QuicSimpleServerSession : public QuicServerSessionBase { |
public: |
+ // A PromisedStreamInfo is an element of the queue to store promised |
+ // stream which hasn't been created yet. It keeps a mapping between promised |
+ // stream id with its priority and the headers sent out in PUSH_PROMISE. |
+ struct PromisedStreamInfo { |
+ public: |
+ PromisedStreamInfo(SpdyHeaderBlock request_headers, |
+ QuicStreamId stream_id, |
+ SpdyPriority priority) |
+ : request_headers(request_headers), |
+ stream_id(stream_id), |
+ priority(priority), |
+ is_cancelled(false) {} |
+ SpdyHeaderBlock request_headers; |
+ QuicStreamId stream_id; |
+ SpdyPriority priority; |
+ bool is_cancelled; |
+ }; |
+ |
QuicSimpleServerSession(const QuicConfig& config, |
QuicConnection* connection, |
QuicServerSessionVisitor* visitor, |
@@ -45,18 +64,87 @@ class QuicSimpleServerSession : public QuicServerSessionBase { |
~QuicSimpleServerSession() override; |
+ // When a stream is marked draining, it will decrease the number of open |
+ // streams. If it is an outgoing stream, try to open a new stream to send |
+ // remaing push responses. |
+ void StreamDraining(QuicStreamId id) override; |
+ |
+ // Override base class to detact client sending data on server push stream. |
+ void OnStreamFrame(const QuicStreamFrame& frame) override; |
+ |
+ // Send out PUSH_PROMISE for all |resources| promised stream id in each frame |
+ // will increase by 2 for each item in |resources|. |
+ // And enqueue HEADERS block in those PUSH_PROMISED for sending push response |
+ // later. |
+ virtual void PromisePushResources( |
+ const string& request_url, |
+ const list<QuicInMemoryCache::ServerPushInfo>& resources, |
+ QuicStreamId original_stream_id, |
+ const SpdyHeaderBlock& original_request_headers); |
+ |
protected: |
// QuicSession methods: |
QuicSpdyStream* CreateIncomingDynamicStream(QuicStreamId id) override; |
QuicSimpleServerStream* CreateOutgoingDynamicStream( |
SpdyPriority priority) override; |
- |
+ // Closing an outgoing stream can reduce open outgoing stream count, try |
+ // to handle queued promised streams right now. |
+ void CloseStreamInner(QuicStreamId stream_id, bool locally_reset) override; |
+ // Override to return true for locally preserved server push stream. |
+ void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id) override; |
+ // Override to handle reseting locally preserved streams. |
+ void HandleRstOnValidNonexistentStream( |
+ const QuicRstStreamFrame& frame) override; |
+ |
+ // QuicServerSessionBaseMethod: |
QuicCryptoServerStreamBase* CreateQuicCryptoServerStream( |
const QuicCryptoServerConfig* crypto_config) override; |
private: |
friend class test::QuicSimpleServerSessionPeer; |
+ // Create a server push headers block by copying request's headers block. |
+ // But replace or add these pseudo-headers as they are specific to each |
+ // request: |
+ // :authority, :path, :method, :scheme, referer. |
+ // Copying the rest headers ensures they are the same as the original |
+ // request, especially cookies. |
+ SpdyHeaderBlock SynthesizePushRequestHeaders( |
+ string request_url, |
+ QuicInMemoryCache::ServerPushInfo resource, |
+ const SpdyHeaderBlock& original_request_headers); |
+ |
+ // Send PUSH_PROMISE frame on headers stream. |
+ void SendPushPromise(QuicStreamId original_stream_id, |
+ QuicStreamId promised_stream_id, |
+ const SpdyHeaderBlock& headers); |
+ |
+ // Fetch response from cache for request headers enqueued into |
+ // promised_headers_and_streams_ and send them on dedicated stream until |
+ // reaches max_open_stream_ limit. |
+ // Called when return value of GetNumOpenOutgoingStreams() changes: |
+ // CloseStreamInner(); |
+ // StreamDraining(); |
+ // Note that updateFlowControlOnFinalReceivedByteOffset() won't change the |
+ // return value becasue all push streams are impossible to become locally |
+ // closed. Since a locally preserved stream becomes remotely closed after |
+ // HandlePromisedPushRequests() starts to process it, and if it is reset |
+ // locally afterwards, it will be immediately become closed and never get into |
+ // locally_closed_stream_highest_offset_. So all the streams in this map |
+ // are not outgoing streams. |
+ void HandlePromisedPushRequests(); |
+ |
+ // Keep track of the highest stream id which has been sent in PUSH_PROMISE. |
+ QuicStreamId highest_promised_stream_id_; |
+ |
+ // Promised streams which hasn't been created yet because of max_open_stream_ |
+ // limit. New element is added to the end of the queue. |
+ // Since outgoing stream is created in sequence, stream_id of each element in |
+ // the queue also increases by 2 from previous one's. The front element's |
+ // stream_id is always next_outgoing_stream_id_, and the last one is always |
+ // highest_promised_stream_id_. |
+ std::deque<PromisedStreamInfo> promised_streams_; |
+ |
DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerSession); |
}; |