| 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 |