Home | History | Annotate | Download | only in quic
      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