| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // A toy server specific QuicSession subclass. | 
 |  | 
 | #ifndef QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_SESSION_H_ | 
 | #define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_SESSION_H_ | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <list> | 
 | #include <memory> | 
 | #include <set> | 
 | #include <string> | 
 | #include <utility> | 
 | #include <vector> | 
 |  | 
 | #include "net/third_party/quiche/src/quic/core/http/quic_server_session_base.h" | 
 | #include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h" | 
 | #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h" | 
 | #include "net/third_party/quiche/src/quic/core/quic_packets.h" | 
 | #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" | 
 | #include "net/third_party/quiche/src/quic/tools/quic_backend_response.h" | 
 | #include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h" | 
 | #include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | namespace test { | 
 | class QuicSimpleServerSessionPeer; | 
 | }  // namespace test | 
 |  | 
 | 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(spdy::SpdyHeaderBlock request_headers, | 
 |                        QuicStreamId stream_id, | 
 |                        const spdy::SpdyStreamPrecedence& precedence) | 
 |         : request_headers(std::move(request_headers)), | 
 |           stream_id(stream_id), | 
 |           precedence(precedence), | 
 |           is_cancelled(false) {} | 
 |     spdy::SpdyHeaderBlock request_headers; | 
 |     QuicStreamId stream_id; | 
 |     spdy::SpdyStreamPrecedence precedence; | 
 |     bool is_cancelled; | 
 |   }; | 
 |  | 
 |   // Takes ownership of |connection|. | 
 |   QuicSimpleServerSession(const QuicConfig& config, | 
 |                           const ParsedQuicVersionVector& supported_versions, | 
 |                           QuicConnection* connection, | 
 |                           QuicSession::Visitor* visitor, | 
 |                           QuicCryptoServerStreamBase::Helper* helper, | 
 |                           const QuicCryptoServerConfig* crypto_config, | 
 |                           QuicCompressedCertsCache* compressed_certs_cache, | 
 |                           QuicSimpleServerBackend* quic_simple_server_backend); | 
 |   QuicSimpleServerSession(const QuicSimpleServerSession&) = delete; | 
 |   QuicSimpleServerSession& operator=(const QuicSimpleServerSession&) = delete; | 
 |  | 
 |   ~QuicSimpleServerSession() 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 std::string& request_url, | 
 |       const std::list<QuicBackendResponse::ServerPushInfo>& resources, | 
 |       QuicStreamId original_stream_id, | 
 |       const spdy::SpdyStreamPrecedence& original_precedence, | 
 |       const spdy::SpdyHeaderBlock& original_request_headers); | 
 |  | 
 |   void OnCanCreateNewOutgoingStream(bool unidirectional) override; | 
 |  | 
 |  protected: | 
 |   // QuicSession methods: | 
 |   QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override; | 
 |   QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override; | 
 |   QuicSimpleServerStream* CreateOutgoingBidirectionalStream() override; | 
 |   QuicSimpleServerStream* CreateOutgoingUnidirectionalStream() 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: | 
 |   std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream( | 
 |       const QuicCryptoServerConfig* crypto_config, | 
 |       QuicCompressedCertsCache* compressed_certs_cache) override; | 
 |  | 
 |   QuicSimpleServerBackend* server_backend() { | 
 |     return quic_simple_server_backend_; | 
 |   } | 
 |  | 
 |   void MaybeInitializeHttp3UnidirectionalStreams() 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. | 
 |   spdy::SpdyHeaderBlock SynthesizePushRequestHeaders( | 
 |       std::string request_url, | 
 |       QuicBackendResponse::ServerPushInfo resource, | 
 |       const spdy::SpdyHeaderBlock& original_request_headers); | 
 |  | 
 |   // Send PUSH_PROMISE frame on headers stream. | 
 |   void SendPushPromise(QuicStreamId original_stream_id, | 
 |                        QuicStreamId promised_stream_id, | 
 |                        spdy::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_. | 
 |   QuicCircularDeque<PromisedStreamInfo> promised_streams_; | 
 |  | 
 |   QuicSimpleServerBackend* quic_simple_server_backend_;  // Not owned. | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_SESSION_H_ |