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