OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 // | |
5 // A QuicSession, which demuxes a single connection to individual streams. | |
6 | |
7 #ifndef NET_QUIC_QUIC_SESSION_H_ | |
8 #define NET_QUIC_QUIC_SESSION_H_ | |
9 | |
10 #include <stddef.h> | |
11 | |
12 #include <map> | |
13 #include <memory> | |
14 #include <string> | |
15 #include <unordered_map> | |
16 #include <unordered_set> | |
17 #include <vector> | |
18 | |
19 #include "base/compiler_specific.h" | |
20 #include "base/containers/small_map.h" | |
21 #include "base/macros.h" | |
22 #include "base/strings/string_piece.h" | |
23 #include "net/base/ip_endpoint.h" | |
24 #include "net/quic/quic_connection.h" | |
25 #include "net/quic/quic_crypto_stream.h" | |
26 #include "net/quic/quic_packet_creator.h" | |
27 #include "net/quic/quic_protocol.h" | |
28 #include "net/quic/quic_write_blocked_list.h" | |
29 #include "net/quic/reliable_quic_stream.h" | |
30 | |
31 namespace net { | |
32 | |
33 class QuicCryptoStream; | |
34 class QuicFlowController; | |
35 class ReliableQuicStream; | |
36 | |
37 namespace test { | |
38 class QuicSessionPeer; | |
39 } // namespace test | |
40 | |
41 class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { | |
42 public: | |
43 // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream. | |
44 enum CryptoHandshakeEvent { | |
45 // ENCRYPTION_FIRST_ESTABLISHED indicates that a full client hello has been | |
46 // sent by a client and that subsequent packets will be encrypted. (Client | |
47 // only.) | |
48 ENCRYPTION_FIRST_ESTABLISHED, | |
49 // ENCRYPTION_REESTABLISHED indicates that a client hello was rejected by | |
50 // the server and thus the encryption key has been updated. Therefore the | |
51 // connection should resend any packets that were sent under | |
52 // ENCRYPTION_INITIAL. (Client only.) | |
53 ENCRYPTION_REESTABLISHED, | |
54 // HANDSHAKE_CONFIRMED, in a client, indicates the the server has accepted | |
55 // our handshake. In a server it indicates that a full, valid client hello | |
56 // has been received. (Client and server.) | |
57 HANDSHAKE_CONFIRMED, | |
58 }; | |
59 | |
60 // Takes ownership of |connection|. | |
61 QuicSession(QuicConnection* connection, const QuicConfig& config); | |
62 | |
63 ~QuicSession() override; | |
64 | |
65 virtual void Initialize(); | |
66 | |
67 // QuicConnectionVisitorInterface methods: | |
68 void OnStreamFrame(const QuicStreamFrame& frame) override; | |
69 void OnRstStream(const QuicRstStreamFrame& frame) override; | |
70 void OnGoAway(const QuicGoAwayFrame& frame) override; | |
71 void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override; | |
72 void OnBlockedFrame(const QuicBlockedFrame& frame) override; | |
73 void OnConnectionClosed(QuicErrorCode error, | |
74 const std::string& error_details, | |
75 ConnectionCloseSource source) override; | |
76 void OnWriteBlocked() override {} | |
77 void OnSuccessfulVersionNegotiation(const QuicVersion& version) override; | |
78 void OnCanWrite() override; | |
79 void OnCongestionWindowChange(QuicTime /*now*/) override {} | |
80 void OnConnectionMigration(PeerAddressChangeType type) override {} | |
81 // Deletes streams that are safe to be deleted now that it's safe to do so (no | |
82 // other operations are being done on the streams at this time). | |
83 void PostProcessAfterData() override; | |
84 bool WillingAndAbleToWrite() const override; | |
85 bool HasPendingHandshake() const override; | |
86 bool HasOpenDynamicStreams() const override; | |
87 void OnPathDegrading() override; | |
88 | |
89 // Called on every incoming packet. Passes |packet| through to |connection_|. | |
90 virtual void ProcessUdpPacket(const IPEndPoint& self_address, | |
91 const IPEndPoint& peer_address, | |
92 const QuicReceivedPacket& packet); | |
93 | |
94 // Called by streams when they want to write data to the peer. | |
95 // Returns a pair with the number of bytes consumed from data, and a boolean | |
96 // indicating if the fin bit was consumed. This does not indicate the data | |
97 // has been sent on the wire: it may have been turned into a packet and queued | |
98 // if the socket was unexpectedly blocked. | |
99 // If provided, |ack_notifier_delegate| will be registered to be notified when | |
100 // we have seen ACKs for all packets resulting from this call. | |
101 virtual QuicConsumedData WritevData( | |
102 ReliableQuicStream* stream, | |
103 QuicStreamId id, | |
104 QuicIOVector iov, | |
105 QuicStreamOffset offset, | |
106 bool fin, | |
107 QuicAckListenerInterface* ack_notifier_delegate); | |
108 | |
109 // Called by streams when they want to close the stream in both directions. | |
110 virtual void SendRstStream(QuicStreamId id, | |
111 QuicRstStreamErrorCode error, | |
112 QuicStreamOffset bytes_written); | |
113 | |
114 // Called when the session wants to go away and not accept any new streams. | |
115 void SendGoAway(QuicErrorCode error_code, const std::string& reason); | |
116 | |
117 // Removes the stream associated with 'stream_id' from the active stream map. | |
118 virtual void CloseStream(QuicStreamId stream_id); | |
119 | |
120 // Returns true if outgoing packets will be encrypted, even if the server | |
121 // hasn't confirmed the handshake yet. | |
122 virtual bool IsEncryptionEstablished(); | |
123 | |
124 // For a client, returns true if the server has confirmed our handshake. For | |
125 // a server, returns true if a full, valid client hello has been received. | |
126 virtual bool IsCryptoHandshakeConfirmed(); | |
127 | |
128 // Called by the QuicCryptoStream when a new QuicConfig has been negotiated. | |
129 virtual void OnConfigNegotiated(); | |
130 | |
131 // Called by the QuicCryptoStream when the handshake enters a new state. | |
132 // | |
133 // Clients will call this function in the order: | |
134 // ENCRYPTION_FIRST_ESTABLISHED | |
135 // zero or more ENCRYPTION_REESTABLISHED | |
136 // HANDSHAKE_CONFIRMED | |
137 // | |
138 // Servers will simply call it once with HANDSHAKE_CONFIRMED. | |
139 virtual void OnCryptoHandshakeEvent(CryptoHandshakeEvent event); | |
140 | |
141 // Called by the QuicCryptoStream when a handshake message is sent. | |
142 virtual void OnCryptoHandshakeMessageSent( | |
143 const CryptoHandshakeMessage& message); | |
144 | |
145 // Called by the QuicCryptoStream when a handshake message is received. | |
146 virtual void OnCryptoHandshakeMessageReceived( | |
147 const CryptoHandshakeMessage& message); | |
148 | |
149 // Returns mutable config for this session. Returned config is owned | |
150 // by QuicSession. | |
151 QuicConfig* config(); | |
152 | |
153 // Returns true if the stream existed previously and has been closed. | |
154 // Returns false if the stream is still active or if the stream has | |
155 // not yet been created. | |
156 bool IsClosedStream(QuicStreamId id); | |
157 | |
158 QuicConnection* connection() { return connection_.get(); } | |
159 const QuicConnection* connection() const { return connection_.get(); } | |
160 size_t num_active_requests() const { return dynamic_stream_map_.size(); } | |
161 const IPEndPoint& peer_address() const { return connection_->peer_address(); } | |
162 QuicConnectionId connection_id() const { | |
163 return connection_->connection_id(); | |
164 } | |
165 | |
166 // Returns the number of currently open streams, excluding the reserved | |
167 // headers and crypto streams, and never counting unfinished streams. | |
168 virtual size_t GetNumActiveStreams() const; | |
169 | |
170 // Returns the number of currently open peer initiated streams, excluding the | |
171 // reserved headers and crypto streams. | |
172 virtual size_t GetNumOpenIncomingStreams() const; | |
173 | |
174 // Returns the number of currently open self initiated streams, excluding the | |
175 // reserved headers and crypto streams. | |
176 virtual size_t GetNumOpenOutgoingStreams() const; | |
177 | |
178 // Returns the number of "available" streams, the stream ids less than | |
179 // largest_peer_created_stream_id_ that have not yet been opened. | |
180 virtual size_t GetNumAvailableStreams() const; | |
181 | |
182 // Add the stream to the session's write-blocked list because it is blocked by | |
183 // connection-level flow control but not by its own stream-level flow control. | |
184 // The stream will be given a chance to write when a connection-level | |
185 // WINDOW_UPDATE arrives. | |
186 void MarkConnectionLevelWriteBlocked(QuicStreamId id); | |
187 | |
188 // Returns true if the session has data to be sent, either queued in the | |
189 // connection, or in a write-blocked stream. | |
190 bool HasDataToWrite() const; | |
191 | |
192 bool goaway_sent() const; | |
193 | |
194 bool goaway_received() const; | |
195 | |
196 QuicErrorCode error() const { return error_; } | |
197 | |
198 Perspective perspective() const { return connection_->perspective(); } | |
199 | |
200 QuicFlowController* flow_controller() { return &flow_controller_; } | |
201 | |
202 // Returns true if connection is flow controller blocked. | |
203 bool IsConnectionFlowControlBlocked() const; | |
204 | |
205 // Returns true if any stream is flow controller blocked. | |
206 bool IsStreamFlowControlBlocked(); | |
207 | |
208 size_t max_open_incoming_streams() const { | |
209 return max_open_incoming_streams_; | |
210 } | |
211 | |
212 size_t max_open_outgoing_streams() const { | |
213 return max_open_outgoing_streams_; | |
214 } | |
215 | |
216 size_t MaxAvailableStreams() const; | |
217 | |
218 // Returns existing static or dynamic stream with id = |stream_id|. If no | |
219 // such stream exists, and |stream_id| is a peer-created dynamic stream id, | |
220 // then a new stream is created and returned. In all other cases, nullptr is | |
221 // returned. | |
222 ReliableQuicStream* GetOrCreateStream(const QuicStreamId stream_id); | |
223 | |
224 // Mark a stream as draining. | |
225 virtual void StreamDraining(QuicStreamId id); | |
226 | |
227 // Returns true if this stream should yield writes to another blocked stream. | |
228 bool ShouldYield(QuicStreamId stream_id); | |
229 | |
230 protected: | |
231 using StaticStreamMap = | |
232 base::SmallMap<std::unordered_map<QuicStreamId, ReliableQuicStream*>, 2>; | |
233 | |
234 using DynamicStreamMap = | |
235 base::SmallMap<std::unordered_map<QuicStreamId, ReliableQuicStream*>, 10>; | |
236 | |
237 // Creates a new stream to handle a peer-initiated stream. | |
238 // Caller does not own the returned stream. | |
239 // Returns nullptr and does error handling if the stream can not be created. | |
240 virtual ReliableQuicStream* CreateIncomingDynamicStream(QuicStreamId id) = 0; | |
241 | |
242 // Create a new stream to handle a locally-initiated stream. | |
243 // Caller does not own the returned stream. | |
244 // Returns nullptr if max streams have already been opened. | |
245 virtual ReliableQuicStream* CreateOutgoingDynamicStream( | |
246 SpdyPriority priority) = 0; | |
247 | |
248 // Return the reserved crypto stream. | |
249 virtual QuicCryptoStream* GetCryptoStream() = 0; | |
250 | |
251 // Adds |stream| to the dynamic stream map. | |
252 // Takes ownership of |stream|. | |
253 virtual void ActivateStream(ReliableQuicStream* stream); | |
254 | |
255 // Returns the stream ID for a new outgoing stream, and increments the | |
256 // underlying counter. | |
257 QuicStreamId GetNextOutgoingStreamId(); | |
258 | |
259 // Returns existing stream with id = |stream_id|. If no such stream exists, | |
260 // and |stream_id| is a peer-created id, then a new stream is created and | |
261 // returned. However if |stream_id| is a locally-created id and no such stream | |
262 // exists, the connection is closed. | |
263 // Caller does not own the returned stream. | |
264 ReliableQuicStream* GetOrCreateDynamicStream(QuicStreamId stream_id); | |
265 | |
266 // Performs the work required to close |stream_id|. If |locally_reset| | |
267 // then the stream has been reset by this endpoint, not by the peer. | |
268 virtual void CloseStreamInner(QuicStreamId stream_id, bool locally_reset); | |
269 | |
270 // When a stream is closed locally, it may not yet know how many bytes the | |
271 // peer sent on that stream. | |
272 // When this data arrives (via stream frame w. FIN, or RST) this method | |
273 // is called, and correctly updates the connection level flow controller. | |
274 void UpdateFlowControlOnFinalReceivedByteOffset( | |
275 QuicStreamId id, | |
276 QuicStreamOffset final_byte_offset); | |
277 | |
278 // Return true if given stream is peer initiated. | |
279 bool IsIncomingStream(QuicStreamId id) const; | |
280 | |
281 StaticStreamMap& static_streams() { return static_stream_map_; } | |
282 const StaticStreamMap& static_streams() const { return static_stream_map_; } | |
283 | |
284 DynamicStreamMap& dynamic_streams() { return dynamic_stream_map_; } | |
285 const DynamicStreamMap& dynamic_streams() const { | |
286 return dynamic_stream_map_; | |
287 } | |
288 | |
289 std::vector<ReliableQuicStream*>* closed_streams() { | |
290 return &closed_streams_; | |
291 } | |
292 | |
293 void set_max_open_incoming_streams(size_t max_open_incoming_streams); | |
294 void set_max_open_outgoing_streams(size_t max_open_outgoing_streams); | |
295 | |
296 void set_largest_peer_created_stream_id( | |
297 QuicStreamId largest_peer_created_stream_id) { | |
298 largest_peer_created_stream_id_ = largest_peer_created_stream_id; | |
299 } | |
300 void set_error(QuicErrorCode error) { error_ = error; } | |
301 QuicWriteBlockedList* write_blocked_streams() { | |
302 return &write_blocked_streams_; | |
303 } | |
304 | |
305 size_t GetNumDynamicOutgoingStreams() const; | |
306 | |
307 size_t GetNumDrainingOutgoingStreams() const; | |
308 | |
309 size_t num_locally_closed_incoming_streams_highest_offset() const { | |
310 return num_locally_closed_incoming_streams_highest_offset_; | |
311 } | |
312 | |
313 size_t GetNumLocallyClosedOutgoingStreamsHighestOffset() const; | |
314 | |
315 // Returns true if the stream is still active. | |
316 bool IsOpenStream(QuicStreamId id); | |
317 | |
318 QuicStreamId next_outgoing_stream_id() const { | |
319 return next_outgoing_stream_id_; | |
320 } | |
321 | |
322 // Close connection when receive a frame for a locally-created nonexistant | |
323 // stream. | |
324 // Prerequisite: IsClosedStream(stream_id) == false | |
325 // Server session might need to override this method to allow server push | |
326 // stream to be promised before creating an active stream. | |
327 virtual void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id); | |
328 | |
329 bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id); | |
330 | |
331 void InsertLocallyClosedStreamsHighestOffset(const QuicStreamId id, | |
332 QuicStreamOffset offset); | |
333 // If stream is a locally closed stream, this RST will update FIN offset. | |
334 // Otherwise stream is a preserved stream and the behavior of it depends on | |
335 // derived class's own implementation. | |
336 virtual void HandleRstOnValidNonexistentStream( | |
337 const QuicRstStreamFrame& frame); | |
338 | |
339 private: | |
340 friend class test::QuicSessionPeer; | |
341 | |
342 // Called in OnConfigNegotiated when we receive a new stream level flow | |
343 // control window in a negotiated config. Closes the connection if invalid. | |
344 void OnNewStreamFlowControlWindow(QuicStreamOffset new_window); | |
345 | |
346 // Called in OnConfigNegotiated when we receive a new connection level flow | |
347 // control window in a negotiated config. Closes the connection if invalid. | |
348 void OnNewSessionFlowControlWindow(QuicStreamOffset new_window); | |
349 | |
350 // Keep track of highest received byte offset of locally closed streams, while | |
351 // waiting for a definitive final highest offset from the peer. | |
352 std::map<QuicStreamId, QuicStreamOffset> | |
353 locally_closed_streams_highest_offset_; | |
354 | |
355 std::unique_ptr<QuicConnection> connection_; | |
356 | |
357 std::vector<ReliableQuicStream*> closed_streams_; | |
358 | |
359 QuicConfig config_; | |
360 | |
361 // The maximum number of outgoing streams this connection can open. | |
362 size_t max_open_outgoing_streams_; | |
363 | |
364 // The maximum number of incoming streams this connection will allow. | |
365 size_t max_open_incoming_streams_; | |
366 | |
367 // Static streams, such as crypto and header streams. Owned by child classes | |
368 // that create these streams. | |
369 StaticStreamMap static_stream_map_; | |
370 | |
371 // Map from StreamId to pointers to streams. Owns the streams. | |
372 DynamicStreamMap dynamic_stream_map_; | |
373 | |
374 // The ID to use for the next outgoing stream. | |
375 QuicStreamId next_outgoing_stream_id_; | |
376 | |
377 // Set of stream ids that are less than the largest stream id that has been | |
378 // received, but are nonetheless available to be created. | |
379 std::unordered_set<QuicStreamId> available_streams_; | |
380 | |
381 // Set of stream ids that are "draining" -- a FIN has been sent and received, | |
382 // but the stream object still exists because not all the received data has | |
383 // been consumed. | |
384 std::unordered_set<QuicStreamId> draining_streams_; | |
385 | |
386 // A list of streams which need to write more data. | |
387 QuicWriteBlockedList write_blocked_streams_; | |
388 | |
389 QuicStreamId largest_peer_created_stream_id_; | |
390 | |
391 // A counter for peer initiated streams which are in the dynamic_stream_map_. | |
392 size_t num_dynamic_incoming_streams_; | |
393 | |
394 // A counter for peer initiated streams which are in the draining_streams_. | |
395 size_t num_draining_incoming_streams_; | |
396 | |
397 // A counter for peer initiated streams which are in the | |
398 // locally_closed_streams_highest_offset_. | |
399 size_t num_locally_closed_incoming_streams_highest_offset_; | |
400 | |
401 // The latched error with which the connection was closed. | |
402 QuicErrorCode error_; | |
403 | |
404 // Used for connection-level flow control. | |
405 QuicFlowController flow_controller_; | |
406 | |
407 // The stream id which was last popped in OnCanWrite, or 0, if not under the | |
408 // call stack of OnCanWrite. | |
409 QuicStreamId currently_writing_stream_id_; | |
410 | |
411 DISALLOW_COPY_AND_ASSIGN(QuicSession); | |
412 }; | |
413 | |
414 } // namespace net | |
415 | |
416 #endif // NET_QUIC_QUIC_SESSION_H_ | |
OLD | NEW |