blob: 2bf645d244855640c50344b5f19eda82cd6675e4 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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// A toy server specific QuicSession subclass.
6
7#ifndef QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_SESSION_H_
8#define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_SESSION_H_
9
10#include <stdint.h>
11
12#include <list>
13#include <memory>
14#include <set>
15#include <string>
16#include <utility>
17#include <vector>
18
QUICHE teama6ef0a62019-03-07 20:34:33 -050019#include "net/third_party/quiche/src/quic/core/http/quic_server_session_base.h"
20#include "net/third_party/quiche/src/quic/core/http/quic_spdy_session.h"
21#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h"
22#include "net/third_party/quiche/src/quic/core/quic_packets.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
24#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
25#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
26#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
27
28namespace quic {
29
30namespace test {
31class QuicSimpleServerSessionPeer;
32} // namespace test
33
34class QuicSimpleServerSession : public QuicServerSessionBase {
35 public:
36 // A PromisedStreamInfo is an element of the queue to store promised
37 // stream which hasn't been created yet. It keeps a mapping between promised
38 // stream id with its priority and the headers sent out in PUSH_PROMISE.
39 struct PromisedStreamInfo {
40 public:
41 PromisedStreamInfo(spdy::SpdyHeaderBlock request_headers,
42 QuicStreamId stream_id,
fayang9a423762019-07-31 08:12:58 -070043 const spdy::SpdyStreamPrecedence& precedence)
QUICHE teama6ef0a62019-03-07 20:34:33 -050044 : request_headers(std::move(request_headers)),
45 stream_id(stream_id),
fayang9a423762019-07-31 08:12:58 -070046 precedence(precedence),
QUICHE teama6ef0a62019-03-07 20:34:33 -050047 is_cancelled(false) {}
48 spdy::SpdyHeaderBlock request_headers;
49 QuicStreamId stream_id;
fayang9a423762019-07-31 08:12:58 -070050 spdy::SpdyStreamPrecedence precedence;
QUICHE teama6ef0a62019-03-07 20:34:33 -050051 bool is_cancelled;
52 };
53
54 // Takes ownership of |connection|.
55 QuicSimpleServerSession(const QuicConfig& config,
56 const ParsedQuicVersionVector& supported_versions,
57 QuicConnection* connection,
58 QuicSession::Visitor* visitor,
nharper5f23a2d2020-02-20 10:44:09 -080059 QuicCryptoServerStreamBase::Helper* helper,
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 const QuicCryptoServerConfig* crypto_config,
61 QuicCompressedCertsCache* compressed_certs_cache,
62 QuicSimpleServerBackend* quic_simple_server_backend);
63 QuicSimpleServerSession(const QuicSimpleServerSession&) = delete;
64 QuicSimpleServerSession& operator=(const QuicSimpleServerSession&) = delete;
65
66 ~QuicSimpleServerSession() override;
67
68 // Override base class to detact client sending data on server push stream.
69 void OnStreamFrame(const QuicStreamFrame& frame) override;
70
71 // Send out PUSH_PROMISE for all |resources| promised stream id in each frame
72 // will increase by 2 for each item in |resources|.
73 // And enqueue HEADERS block in those PUSH_PROMISED for sending push response
74 // later.
75 virtual void PromisePushResources(
vasilvvc48c8712019-03-11 13:38:16 -070076 const std::string& request_url,
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 const std::list<QuicBackendResponse::ServerPushInfo>& resources,
78 QuicStreamId original_stream_id,
fayang9a423762019-07-31 08:12:58 -070079 const spdy::SpdyStreamPrecedence& original_precedence,
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 const spdy::SpdyHeaderBlock& original_request_headers);
81
fkastenholz8556dc22019-07-18 12:42:38 -070082 void OnCanCreateNewOutgoingStream(bool unidirectional) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050083
84 protected:
85 // QuicSession methods:
86 QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override;
renjietangbaea59c2019-05-29 15:08:14 -070087 QuicSpdyStream* CreateIncomingStream(PendingStream* pending) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050088 QuicSimpleServerStream* CreateOutgoingBidirectionalStream() override;
89 QuicSimpleServerStream* CreateOutgoingUnidirectionalStream() override;
90 // Override to return true for locally preserved server push stream.
91 void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id) override;
92 // Override to handle reseting locally preserved streams.
93 void HandleRstOnValidNonexistentStream(
94 const QuicRstStreamFrame& frame) override;
95
96 // QuicServerSessionBaseMethod:
nharpere5e28f92020-01-03 14:10:07 -080097 std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
QUICHE teama6ef0a62019-03-07 20:34:33 -050098 const QuicCryptoServerConfig* crypto_config,
99 QuicCompressedCertsCache* compressed_certs_cache) override;
100
101 QuicSimpleServerBackend* server_backend() {
102 return quic_simple_server_backend_;
103 }
104
renjietang1a33a0c2019-08-12 12:05:31 -0700105 void MaybeInitializeHttp3UnidirectionalStreams() override;
106
QUICHE teama6ef0a62019-03-07 20:34:33 -0500107 private:
108 friend class test::QuicSimpleServerSessionPeer;
109
110 // Create a server push headers block by copying request's headers block.
111 // But replace or add these pseudo-headers as they are specific to each
112 // request:
113 // :authority, :path, :method, :scheme, referer.
114 // Copying the rest headers ensures they are the same as the original
115 // request, especially cookies.
116 spdy::SpdyHeaderBlock SynthesizePushRequestHeaders(
vasilvvc48c8712019-03-11 13:38:16 -0700117 std::string request_url,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500118 QuicBackendResponse::ServerPushInfo resource,
119 const spdy::SpdyHeaderBlock& original_request_headers);
120
121 // Send PUSH_PROMISE frame on headers stream.
122 void SendPushPromise(QuicStreamId original_stream_id,
123 QuicStreamId promised_stream_id,
124 spdy::SpdyHeaderBlock headers);
125
126 // Fetch response from cache for request headers enqueued into
127 // promised_headers_and_streams_ and send them on dedicated stream until
128 // reaches max_open_stream_ limit.
129 // Called when return value of GetNumOpenOutgoingStreams() changes:
130 // CloseStreamInner();
131 // StreamDraining();
132 // Note that updateFlowControlOnFinalReceivedByteOffset() won't change the
133 // return value becasue all push streams are impossible to become locally
134 // closed. Since a locally preserved stream becomes remotely closed after
135 // HandlePromisedPushRequests() starts to process it, and if it is reset
136 // locally afterwards, it will be immediately become closed and never get into
137 // locally_closed_stream_highest_offset_. So all the streams in this map
138 // are not outgoing streams.
139 void HandlePromisedPushRequests();
140
141 // Keep track of the highest stream id which has been sent in PUSH_PROMISE.
142 QuicStreamId highest_promised_stream_id_;
143
144 // Promised streams which hasn't been created yet because of max_open_stream_
145 // limit. New element is added to the end of the queue.
146 // Since outgoing stream is created in sequence, stream_id of each element in
147 // the queue also increases by 2 from previous one's. The front element's
148 // stream_id is always next_outgoing_stream_id_, and the last one is always
149 // highest_promised_stream_id_.
wuba750aab2020-02-10 06:43:15 -0800150 QuicCircularDeque<PromisedStreamInfo> promised_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500151
152 QuicSimpleServerBackend* quic_simple_server_backend_; // Not owned.
153};
154
155} // namespace quic
156
157#endif // QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_SESSION_H_