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 <vector> 11 12 #include "base/compiler_specific.h" 13 #include "base/containers/hash_tables.h" 14 #include "net/base/ip_endpoint.h" 15 #include "net/base/linked_hash_map.h" 16 #include "net/quic/quic_connection.h" 17 #include "net/quic/quic_crypto_stream.h" 18 #include "net/quic/quic_data_stream.h" 19 #include "net/quic/quic_packet_creator.h" 20 #include "net/quic/quic_protocol.h" 21 #include "net/quic/quic_spdy_compressor.h" 22 #include "net/quic/quic_spdy_decompressor.h" 23 #include "net/quic/reliable_quic_stream.h" 24 #include "net/spdy/write_blocked_list.h" 25 26 namespace net { 27 28 class QuicCryptoStream; 29 class ReliableQuicStream; 30 class SSLInfo; 31 class VisitorShim; 32 33 namespace test { 34 class QuicSessionPeer; 35 } // namespace test 36 37 class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface { 38 public: 39 // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream. 40 enum CryptoHandshakeEvent { 41 // ENCRYPTION_FIRST_ESTABLISHED indicates that a full client hello has been 42 // sent by a client and that subsequent packets will be encrypted. (Client 43 // only.) 44 ENCRYPTION_FIRST_ESTABLISHED, 45 // ENCRYPTION_REESTABLISHED indicates that a client hello was rejected by 46 // the server and thus the encryption key has been updated. Therefore the 47 // connection should resend any packets that were sent under 48 // ENCRYPTION_INITIAL. (Client only.) 49 ENCRYPTION_REESTABLISHED, 50 // HANDSHAKE_CONFIRMED, in a client, indicates the the server has accepted 51 // our handshake. In a server it indicates that a full, valid client hello 52 // has been received. (Client and server.) 53 HANDSHAKE_CONFIRMED, 54 }; 55 56 QuicSession(QuicConnection* connection, 57 const QuicConfig& config); 58 59 virtual ~QuicSession(); 60 61 // QuicConnectionVisitorInterface methods: 62 virtual bool OnStreamFrames( 63 const std::vector<QuicStreamFrame>& frames) OVERRIDE; 64 virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE; 65 virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE; 66 virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE; 67 virtual void OnSuccessfulVersionNegotiation( 68 const QuicVersion& version) OVERRIDE {} 69 virtual void OnConfigNegotiated() OVERRIDE; 70 // Not needed for HTTP. 71 virtual bool OnCanWrite() OVERRIDE; 72 virtual bool HasPendingHandshake() const OVERRIDE; 73 74 // Called by streams when they want to write data to the peer. 75 // Returns a pair with the number of bytes consumed from data, and a boolean 76 // indicating if the fin bit was consumed. This does not indicate the data 77 // has been sent on the wire: it may have been turned into a packet and queued 78 // if the socket was unexpectedly blocked. 79 // If provided, |ack_notifier_delegate| will be registered to be notified when 80 // we have seen ACKs for all packets resulting from this call. Not owned by 81 // this class. 82 virtual QuicConsumedData WritevData( 83 QuicStreamId id, 84 const struct iovec* iov, 85 int iov_count, 86 QuicStreamOffset offset, 87 bool fin, 88 QuicAckNotifier::DelegateInterface* ack_notifier_delegate); 89 90 // Called by streams when they want to close the stream in both directions. 91 virtual void SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error); 92 93 // Called when the session wants to go away and not accept any new streams. 94 void SendGoAway(QuicErrorCode error_code, const std::string& reason); 95 96 // Removes the stream associated with 'stream_id' from the active stream map. 97 virtual void CloseStream(QuicStreamId stream_id); 98 99 // Returns true if outgoing packets will be encrypted, even if the server 100 // hasn't confirmed the handshake yet. 101 virtual bool IsEncryptionEstablished(); 102 103 // For a client, returns true if the server has confirmed our handshake. For 104 // a server, returns true if a full, valid client hello has been received. 105 virtual bool IsCryptoHandshakeConfirmed(); 106 107 // Called by the QuicCryptoStream when the handshake enters a new state. 108 // 109 // Clients will call this function in the order: 110 // ENCRYPTION_FIRST_ESTABLISHED 111 // zero or more ENCRYPTION_REESTABLISHED 112 // HANDSHAKE_CONFIRMED 113 // 114 // Servers will simply call it once with HANDSHAKE_CONFIRMED. 115 virtual void OnCryptoHandshakeEvent(CryptoHandshakeEvent event); 116 117 // Called by the QuicCryptoStream when a handshake message is sent. 118 virtual void OnCryptoHandshakeMessageSent( 119 const CryptoHandshakeMessage& message); 120 121 // Called by the QuicCryptoStream when a handshake message is received. 122 virtual void OnCryptoHandshakeMessageReceived( 123 const CryptoHandshakeMessage& message); 124 125 // Returns mutable config for this session. Returned config is owned 126 // by QuicSession. 127 QuicConfig* config(); 128 129 // Returns true if the stream existed previously and has been closed. 130 // Returns false if the stream is still active or if the stream has 131 // not yet been created. 132 bool IsClosedStream(QuicStreamId id); 133 134 QuicConnection* connection() { return connection_.get(); } 135 const QuicConnection* connection() const { return connection_.get(); } 136 size_t num_active_requests() const { return stream_map_.size(); } 137 const IPEndPoint& peer_address() const { 138 return connection_->peer_address(); 139 } 140 QuicGuid guid() const { return connection_->guid(); } 141 142 QuicPacketCreator::Options* options() { return connection()->options(); } 143 144 // Returns the number of currently open streams, including those which have 145 // been implicitly created. 146 virtual size_t GetNumOpenStreams() const; 147 148 void MarkWriteBlocked(QuicStreamId id, QuicPriority priority); 149 150 // Returns true if the session has data to be sent, either queued in the 151 // connection, or in a write-blocked stream. 152 bool HasQueuedData() const; 153 154 // Marks that |stream_id| is blocked waiting to decompress the 155 // headers identified by |decompression_id|. 156 void MarkDecompressionBlocked(QuicHeaderId decompression_id, 157 QuicStreamId stream_id); 158 159 bool goaway_received() const { 160 return goaway_received_; 161 } 162 163 bool goaway_sent() const { 164 return goaway_sent_; 165 } 166 167 QuicSpdyDecompressor* decompressor() { return &decompressor_; } 168 QuicSpdyCompressor* compressor() { return &compressor_; } 169 170 // Gets the SSL connection information. 171 virtual bool GetSSLInfo(SSLInfo* ssl_info); 172 173 QuicErrorCode error() const { return error_; } 174 175 bool is_server() const { return connection_->is_server(); } 176 177 protected: 178 typedef base::hash_map<QuicStreamId, QuicDataStream*> DataStreamMap; 179 180 // Creates a new stream, owned by the caller, to handle a peer-initiated 181 // stream. Returns NULL and does error handling if the stream can not be 182 // created. 183 virtual QuicDataStream* CreateIncomingDataStream(QuicStreamId id) = 0; 184 185 // Create a new stream, owned by the caller, to handle a locally-initiated 186 // stream. Returns NULL if max streams have already been opened. 187 virtual QuicDataStream* CreateOutgoingDataStream() = 0; 188 189 // Return the reserved crypto stream. 190 virtual QuicCryptoStream* GetCryptoStream() = 0; 191 192 // Adds 'stream' to the active stream map. 193 virtual void ActivateStream(QuicDataStream* stream); 194 195 // Returns the stream id for a new stream. 196 QuicStreamId GetNextStreamId(); 197 198 QuicDataStream* GetIncomingReliableStream(QuicStreamId stream_id); 199 200 QuicDataStream* GetDataStream(const QuicStreamId stream_id); 201 202 ReliableQuicStream* GetStream(const QuicStreamId stream_id); 203 204 // This is called after every call other than OnConnectionClose from the 205 // QuicConnectionVisitor to allow post-processing once the work has been done. 206 // In this case, it deletes streams given that it's safe to do so (no other 207 // operations are being done on the streams at this time) 208 virtual void PostProcessAfterData(); 209 210 base::hash_map<QuicStreamId, QuicDataStream*>* streams() { 211 return &stream_map_; 212 } 213 214 const base::hash_map<QuicStreamId, QuicDataStream*>* streams() const { 215 return &stream_map_; 216 } 217 218 std::vector<QuicDataStream*>* closed_streams() { return &closed_streams_; } 219 220 size_t get_max_open_streams() const { 221 return max_open_streams_; 222 } 223 224 private: 225 friend class test::QuicSessionPeer; 226 friend class VisitorShim; 227 228 // Performs the work required to close |stream_id|. If |locally_reset| 229 // then the stream has been reset by this endpoint, not by the peer. This 230 // means the stream may become a zombie stream which needs to stay 231 // around until headers have been decompressed. 232 void CloseStreamInner(QuicStreamId stream_id, bool locally_reset); 233 234 // Adds |stream_id| to the zobmie stream map, closing the oldest 235 // zombie stream if the set is full. 236 void AddZombieStream(QuicStreamId stream_id); 237 238 // Closes the zombie stream |stream_id| and removes it from the zombie 239 // stream map. 240 void CloseZombieStream(QuicStreamId stream_id); 241 242 // Adds |stream_id| to the prematurely closed stream map, removing the 243 // oldest prematurely closed stream if the set is full. 244 void AddPrematurelyClosedStream(QuicStreamId stream_id); 245 246 scoped_ptr<QuicConnection> connection_; 247 248 // Tracks the last 20 streams which closed without decompressing headers. 249 // This is for best-effort detection of an unrecoverable compression context. 250 // Ideally this would be a linked_hash_set as the boolean is unused. 251 linked_hash_map<QuicStreamId, bool> prematurely_closed_streams_; 252 253 // Streams which have been locally reset before decompressing headers 254 // from the peer. These streams need to stay open long enough to 255 // process any headers from the peer. 256 // Ideally this would be a linked_hash_set as the boolean is unused. 257 linked_hash_map<QuicStreamId, bool> zombie_streams_; 258 259 // A shim to stand between the connection and the session, to handle stream 260 // deletions. 261 scoped_ptr<VisitorShim> visitor_shim_; 262 263 std::vector<QuicDataStream*> closed_streams_; 264 265 QuicSpdyDecompressor decompressor_; 266 QuicSpdyCompressor compressor_; 267 268 QuicConfig config_; 269 270 // Returns the maximum number of streams this connection can open. 271 size_t max_open_streams_; 272 273 // Map from StreamId to pointers to streams that are owned by the caller. 274 DataStreamMap stream_map_; 275 QuicStreamId next_stream_id_; 276 277 // Set of stream ids that have been "implicitly created" by receipt 278 // of a stream id larger than the next expected stream id. 279 base::hash_set<QuicStreamId> implicitly_created_streams_; 280 281 // A list of streams which need to write more data. 282 WriteBlockedList<QuicStreamId> write_blocked_streams_; 283 284 // A map of headers waiting to be compressed, and the streams 285 // they are associated with. 286 map<uint32, QuicStreamId> decompression_blocked_streams_; 287 288 QuicStreamId largest_peer_created_stream_id_; 289 290 // The latched error with which the connection was closed. 291 QuicErrorCode error_; 292 293 // Whether a GoAway has been received. 294 bool goaway_received_; 295 // Whether a GoAway has been sent. 296 bool goaway_sent_; 297 298 // Indicate if there is pending data for the crypto stream. 299 bool has_pending_handshake_; 300 301 DISALLOW_COPY_AND_ASSIGN(QuicSession); 302 }; 303 304 } // namespace net 305 306 #endif // NET_QUIC_QUIC_SESSION_H_ 307