1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
// 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 NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_H_
#define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_H_
#include <stdint.h>
#include <set>
#include <string>
#include <vector>
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#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"
namespace net {
class QuicBlockedWriterInterface;
class QuicConfig;
class QuicConnection;
class QuicCryptoServerConfig;
class ReliableQuicStream;
namespace tools {
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(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,
const QuicCryptoServerConfig* crypto_config);
~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);
};
} // namespace tools
} // namespace net
#endif // NET_TOOLS_QUIC_QUIC_SERVER_SESSION_H_
|