1 // Copyright 2019 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 #ifndef QUICHE_QUIC_CORE_QUIC_DATAGRAM_QUEUE_H_ 6 #define QUICHE_QUIC_CORE_QUIC_DATAGRAM_QUEUE_H_ 7 8 #include <cstdint> 9 #include <memory> 10 #include <optional> 11 12 #include "quiche/quic/core/quic_time.h" 13 #include "quiche/quic/core/quic_types.h" 14 #include "quiche/common/platform/api/quiche_mem_slice.h" 15 #include "quiche/common/quiche_circular_deque.h" 16 17 namespace quic { 18 19 class QuicSession; 20 21 // Provides a way to buffer QUIC datagrams (messages) in case they cannot 22 // be sent due to congestion control. Datagrams are buffered for a limited 23 // amount of time, and deleted after that time passes. 24 class QUICHE_EXPORT QuicDatagramQueue { 25 public: 26 // An interface used to monitor events on the associated `QuicDatagramQueue`. 27 class QUICHE_EXPORT Observer { 28 public: 29 virtual ~Observer() = default; 30 31 // Called when a datagram in the associated queue is sent or discarded. 32 // Identity information for the datagram is not given, because the sending 33 // and discarding order is always first-in-first-out. 34 // This function is called synchronously in `QuicDatagramQueue` methods. 35 // `status` is nullopt when the datagram is dropped due to being in the 36 // queue for too long. 37 virtual void OnDatagramProcessed(std::optional<MessageStatus> status) = 0; 38 }; 39 40 // |session| is not owned and must outlive this object. 41 explicit QuicDatagramQueue(QuicSession* session); 42 43 // |session| is not owned and must outlive this object. 44 QuicDatagramQueue(QuicSession* session, std::unique_ptr<Observer> observer); 45 46 // Adds the datagram to the end of the queue. May send it immediately; if 47 // not, MESSAGE_STATUS_BLOCKED is returned. 48 MessageStatus SendOrQueueDatagram(quiche::QuicheMemSlice datagram); 49 50 // Attempts to send a single datagram from the queue. Returns the result of 51 // SendMessage(), or nullopt if there were no unexpired datagrams to send. 52 std::optional<MessageStatus> TrySendingNextDatagram(); 53 54 // Sends all of the unexpired datagrams until either the connection becomes 55 // write-blocked or the queue is empty. Returns the number of datagrams sent. 56 size_t SendDatagrams(); 57 58 // Returns the amount of time a datagram is allowed to be in the queue before 59 // it is dropped. If not set explicitly using SetMaxTimeInQueue(), an 60 // RTT-based heuristic is used. 61 QuicTime::Delta GetMaxTimeInQueue() const; 62 SetMaxTimeInQueue(QuicTime::Delta max_time_in_queue)63 void SetMaxTimeInQueue(QuicTime::Delta max_time_in_queue) { 64 max_time_in_queue_ = max_time_in_queue; 65 } 66 67 // If set to true, all datagrams added into the queue would be sent with the 68 // flush flag set to true, meaning that they will bypass congestion control 69 // and related logic. SetForceFlush(bool force_flush)70 void SetForceFlush(bool force_flush) { force_flush_ = force_flush; } 71 queue_size()72 size_t queue_size() { return queue_.size(); } empty()73 bool empty() { return queue_.empty(); } expired_datagram_count()74 uint64_t expired_datagram_count() const { return expired_datagram_count_; } 75 76 private: 77 struct QUICHE_EXPORT Datagram { 78 quiche::QuicheMemSlice datagram; 79 QuicTime expiry; 80 }; 81 82 // Removes expired datagrams from the front of the queue. 83 void RemoveExpiredDatagrams(); 84 85 QuicSession* session_; // Not owned. 86 const QuicClock* clock_; 87 88 QuicTime::Delta max_time_in_queue_ = QuicTime::Delta::Zero(); 89 quiche::QuicheCircularDeque<Datagram> queue_; 90 std::unique_ptr<Observer> observer_; 91 uint64_t expired_datagram_count_ = 0; 92 bool force_flush_ = false; 93 }; 94 95 } // namespace quic 96 97 #endif // QUICHE_QUIC_CORE_QUIC_DATAGRAM_QUEUE_H_ 98