|  | // Copyright (c) 2018 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. | 
|  |  | 
|  | #ifndef QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_ | 
|  | #define QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_ | 
|  |  | 
|  | #include "absl/container/flat_hash_map.h" | 
|  | #include "quiche/quic/core/quic_interval_set.h" | 
|  | #include "quiche/quic/core/session_notifier_interface.h" | 
|  | #include "quiche/quic/platform/api/quic_test.h" | 
|  | #include "quiche/common/quiche_circular_deque.h" | 
|  | #include "quiche/common/quiche_linked_hash_map.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | class QuicConnection; | 
|  |  | 
|  | namespace test { | 
|  |  | 
|  | // SimpleSessionNotifier implements the basic functionalities of a session, and | 
|  | // it manages stream data and control frames. | 
|  | class SimpleSessionNotifier : public SessionNotifierInterface { | 
|  | public: | 
|  | explicit SimpleSessionNotifier(QuicConnection* connection); | 
|  | ~SimpleSessionNotifier() override; | 
|  |  | 
|  | // Tries to write stream data and returns data consumed. | 
|  | QuicConsumedData WriteOrBufferData(QuicStreamId id, QuicByteCount data_length, | 
|  | StreamSendingState state); | 
|  | QuicConsumedData WriteOrBufferData(QuicStreamId id, QuicByteCount data_length, | 
|  | StreamSendingState state, | 
|  | TransmissionType transmission_type); | 
|  |  | 
|  | // Tries to write RST_STREAM_FRAME. | 
|  | void WriteOrBufferRstStream(QuicStreamId id, QuicRstStreamErrorCode error, | 
|  | QuicStreamOffset bytes_written); | 
|  |  | 
|  | // Tries to write WINDOW_UPDATE. | 
|  | void WriteOrBufferWindowUpate(QuicStreamId id, QuicStreamOffset byte_offset); | 
|  |  | 
|  | // Tries to write PING. | 
|  | void WriteOrBufferPing(); | 
|  |  | 
|  | // Tries to write ACK_FREQUENCY. | 
|  | void WriteOrBufferAckFrequency( | 
|  | const QuicAckFrequencyFrame& ack_frequency_frame); | 
|  |  | 
|  | // Tries to write CRYPTO data and returns the number of bytes written. | 
|  | size_t WriteCryptoData(EncryptionLevel level, QuicByteCount data_length, | 
|  | QuicStreamOffset offset); | 
|  |  | 
|  | // Neuters unencrypted data of crypto stream. | 
|  | void NeuterUnencryptedData(); | 
|  |  | 
|  | // Called when connection_ becomes writable. | 
|  | void OnCanWrite(); | 
|  |  | 
|  | // Called to reset stream. | 
|  | void OnStreamReset(QuicStreamId id, QuicRstStreamErrorCode error); | 
|  |  | 
|  | // Returns true if there are 1) unsent control frames and stream data, or 2) | 
|  | // lost control frames and stream data. | 
|  | bool WillingToWrite() const; | 
|  |  | 
|  | // Number of sent stream bytes. Please note, this does not count | 
|  | // retransmissions. | 
|  | QuicByteCount StreamBytesSent() const; | 
|  |  | 
|  | // Number of stream bytes waiting to be sent for the first time. | 
|  | QuicByteCount StreamBytesToSend() const; | 
|  |  | 
|  | // Returns true if there is any stream data waiting to be sent for the first | 
|  | // time. | 
|  | bool HasBufferedStreamData() const; | 
|  |  | 
|  | // Returns true if stream |id| has any outstanding data. | 
|  | bool StreamIsWaitingForAcks(QuicStreamId id) const; | 
|  |  | 
|  | // SessionNotifierInterface methods: | 
|  | bool OnFrameAcked(const QuicFrame& frame, QuicTime::Delta ack_delay_time, | 
|  | QuicTime receive_timestamp) override; | 
|  | void OnStreamFrameRetransmitted(const QuicStreamFrame& /*frame*/) override {} | 
|  | void OnFrameLost(const QuicFrame& frame) override; | 
|  | bool RetransmitFrames(const QuicFrames& frames, | 
|  | TransmissionType type) override; | 
|  | bool IsFrameOutstanding(const QuicFrame& frame) const override; | 
|  | bool HasUnackedCryptoData() const override; | 
|  | bool HasUnackedStreamData() const override; | 
|  | bool HasLostStreamData() const; | 
|  |  | 
|  | private: | 
|  | struct StreamState { | 
|  | StreamState(); | 
|  | ~StreamState(); | 
|  |  | 
|  | // Total number of bytes. | 
|  | QuicByteCount bytes_total; | 
|  | // Number of sent bytes. | 
|  | QuicByteCount bytes_sent; | 
|  | // Record of acked offsets. | 
|  | QuicIntervalSet<QuicStreamOffset> bytes_acked; | 
|  | // Data considered as lost and needs to be retransmitted. | 
|  | QuicIntervalSet<QuicStreamOffset> pending_retransmissions; | 
|  |  | 
|  | bool fin_buffered; | 
|  | bool fin_sent; | 
|  | bool fin_outstanding; | 
|  | bool fin_lost; | 
|  | }; | 
|  |  | 
|  | friend std::ostream& operator<<(std::ostream& os, const StreamState& s); | 
|  |  | 
|  | using StreamMap = absl::flat_hash_map<QuicStreamId, StreamState>; | 
|  |  | 
|  | void OnStreamDataConsumed(QuicStreamId id, QuicStreamOffset offset, | 
|  | QuicByteCount data_length, bool fin); | 
|  |  | 
|  | bool OnControlFrameAcked(const QuicFrame& frame); | 
|  |  | 
|  | void OnControlFrameLost(const QuicFrame& frame); | 
|  |  | 
|  | bool RetransmitLostControlFrames(); | 
|  |  | 
|  | bool RetransmitLostCryptoData(); | 
|  |  | 
|  | bool RetransmitLostStreamData(); | 
|  |  | 
|  | bool WriteBufferedControlFrames(); | 
|  |  | 
|  | bool WriteBufferedCryptoData(); | 
|  |  | 
|  | bool IsControlFrameOutstanding(const QuicFrame& frame) const; | 
|  |  | 
|  | bool HasBufferedControlFrames() const; | 
|  |  | 
|  | bool StreamHasBufferedData(QuicStreamId id) const; | 
|  |  | 
|  | quiche::QuicheCircularDeque<QuicFrame> control_frames_; | 
|  |  | 
|  | quiche::QuicheLinkedHashMap<QuicControlFrameId, bool> lost_control_frames_; | 
|  |  | 
|  | // Id of latest saved control frame. 0 if no control frame has been saved. | 
|  | QuicControlFrameId last_control_frame_id_; | 
|  |  | 
|  | // The control frame at the 0th index of control_frames_. | 
|  | QuicControlFrameId least_unacked_; | 
|  |  | 
|  | // ID of the least unsent control frame. | 
|  | QuicControlFrameId least_unsent_; | 
|  |  | 
|  | StreamMap stream_map_; | 
|  |  | 
|  | // Transferred crypto bytes according to encryption levels. | 
|  | QuicIntervalSet<QuicStreamOffset> | 
|  | crypto_bytes_transferred_[NUM_ENCRYPTION_LEVELS]; | 
|  |  | 
|  | StreamState crypto_state_[NUM_ENCRYPTION_LEVELS]; | 
|  |  | 
|  | QuicConnection* connection_; | 
|  | }; | 
|  |  | 
|  | }  // namespace test | 
|  |  | 
|  | }  // namespace quic | 
|  |  | 
|  | #endif  // QUICHE_QUIC_TEST_TOOLS_SIMPLE_SESSION_NOTIFIER_H_ |