xref: /aosp_15_r20/external/webrtc/net/dcsctp/rx/reassembly_queue.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #ifndef NET_DCSCTP_RX_REASSEMBLY_QUEUE_H_
11*d9f75844SAndroid Build Coastguard Worker #define NET_DCSCTP_RX_REASSEMBLY_QUEUE_H_
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <set>
18*d9f75844SAndroid Build Coastguard Worker #include <string>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker #include <vector>
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
24*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/common/internal_types.h"
25*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/common/sequence_numbers.h"
26*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
27*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/packet/data.h"
28*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
29*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
30*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/public/dcsctp_handover_state.h"
31*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/public/dcsctp_message.h"
32*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/rx/reassembly_streams.h"
33*d9f75844SAndroid Build Coastguard Worker 
34*d9f75844SAndroid Build Coastguard Worker namespace dcsctp {
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker // Contains the received DATA chunks that haven't yet been reassembled, and
37*d9f75844SAndroid Build Coastguard Worker // reassembles chunks when possible.
38*d9f75844SAndroid Build Coastguard Worker //
39*d9f75844SAndroid Build Coastguard Worker // The actual assembly is handled by an implementation of the
40*d9f75844SAndroid Build Coastguard Worker // `ReassemblyStreams` interface.
41*d9f75844SAndroid Build Coastguard Worker //
42*d9f75844SAndroid Build Coastguard Worker // Except for reassembling fragmented messages, this class will also handle two
43*d9f75844SAndroid Build Coastguard Worker // less common operations; To handle the receiver-side of partial reliability
44*d9f75844SAndroid Build Coastguard Worker // (limited number of retransmissions or limited message lifetime) as well as
45*d9f75844SAndroid Build Coastguard Worker // stream resetting, which is used when a sender wishes to close a data channel.
46*d9f75844SAndroid Build Coastguard Worker //
47*d9f75844SAndroid Build Coastguard Worker // Partial reliability is handled when a FORWARD-TSN or I-FORWARD-TSN chunk is
48*d9f75844SAndroid Build Coastguard Worker // received, and it will simply delete any chunks matching the parameters in
49*d9f75844SAndroid Build Coastguard Worker // that chunk. This is mainly implemented in ReassemblyStreams.
50*d9f75844SAndroid Build Coastguard Worker //
51*d9f75844SAndroid Build Coastguard Worker // Resetting streams is handled when a RECONFIG chunks is received, with an
52*d9f75844SAndroid Build Coastguard Worker // "Outgoing SSN Reset Request" parameter. That parameter will contain a list of
53*d9f75844SAndroid Build Coastguard Worker // streams to reset, and a `sender_last_assigned_tsn`. If this TSN is not yet
54*d9f75844SAndroid Build Coastguard Worker // seen, the stream cannot be directly reset, and this class will respond that
55*d9f75844SAndroid Build Coastguard Worker // the reset is "deferred". But if this TSN provided is known, the stream can be
56*d9f75844SAndroid Build Coastguard Worker // immediately be reset.
57*d9f75844SAndroid Build Coastguard Worker //
58*d9f75844SAndroid Build Coastguard Worker // The ReassemblyQueue has a maximum size, as it would otherwise be an DoS
59*d9f75844SAndroid Build Coastguard Worker // attack vector where a peer could consume all memory of the other peer by
60*d9f75844SAndroid Build Coastguard Worker // sending a lot of ordered chunks, but carefully withholding an early one. It
61*d9f75844SAndroid Build Coastguard Worker // also has a watermark limit, which the caller can query is the number of bytes
62*d9f75844SAndroid Build Coastguard Worker // is above that limit. This is used by the caller to be selective in what to
63*d9f75844SAndroid Build Coastguard Worker // add to the reassembly queue, so that it's not exhausted. The caller is
64*d9f75844SAndroid Build Coastguard Worker // expected to call `is_full` prior to adding data to the queue and to act
65*d9f75844SAndroid Build Coastguard Worker // accordingly if the queue is full.
66*d9f75844SAndroid Build Coastguard Worker class ReassemblyQueue {
67*d9f75844SAndroid Build Coastguard Worker  public:
68*d9f75844SAndroid Build Coastguard Worker   // When the queue is filled over this fraction (of its maximum size), the
69*d9f75844SAndroid Build Coastguard Worker   // socket should restrict incoming data to avoid filling up the queue.
70*d9f75844SAndroid Build Coastguard Worker   static constexpr float kHighWatermarkLimit = 0.9;
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker   ReassemblyQueue(absl::string_view log_prefix,
73*d9f75844SAndroid Build Coastguard Worker                   TSN peer_initial_tsn,
74*d9f75844SAndroid Build Coastguard Worker                   size_t max_size_bytes,
75*d9f75844SAndroid Build Coastguard Worker                   bool use_message_interleaving = false);
76*d9f75844SAndroid Build Coastguard Worker 
77*d9f75844SAndroid Build Coastguard Worker   // Adds a data chunk to the queue, with a `tsn` and other parameters in
78*d9f75844SAndroid Build Coastguard Worker   // `data`.
79*d9f75844SAndroid Build Coastguard Worker   void Add(TSN tsn, Data data);
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker   // Indicates if the reassembly queue has any reassembled messages that can be
82*d9f75844SAndroid Build Coastguard Worker   // retrieved by calling `FlushMessages`.
HasMessages()83*d9f75844SAndroid Build Coastguard Worker   bool HasMessages() const { return !reassembled_messages_.empty(); }
84*d9f75844SAndroid Build Coastguard Worker 
85*d9f75844SAndroid Build Coastguard Worker   // Returns any reassembled messages.
86*d9f75844SAndroid Build Coastguard Worker   std::vector<DcSctpMessage> FlushMessages();
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker   // Handle a ForwardTSN chunk, when the sender has indicated that the received
89*d9f75844SAndroid Build Coastguard Worker   // (this class) should forget about some chunks. This is used to implement
90*d9f75844SAndroid Build Coastguard Worker   // partial reliability.
91*d9f75844SAndroid Build Coastguard Worker   void Handle(const AnyForwardTsnChunk& forward_tsn);
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker   // Given the reset stream request and the current cum_tsn_ack, might either
94*d9f75844SAndroid Build Coastguard Worker   // reset the streams directly (returns kSuccessPerformed), or at a later time,
95*d9f75844SAndroid Build Coastguard Worker   // by entering the "deferred reset processing" mode (returns kInProgress).
96*d9f75844SAndroid Build Coastguard Worker   ReconfigurationResponseParameter::Result ResetStreams(
97*d9f75844SAndroid Build Coastguard Worker       const OutgoingSSNResetRequestParameter& req,
98*d9f75844SAndroid Build Coastguard Worker       TSN cum_tsn_ack);
99*d9f75844SAndroid Build Coastguard Worker 
100*d9f75844SAndroid Build Coastguard Worker   // Given the current (updated) cum_tsn_ack, might leave "defererred reset
101*d9f75844SAndroid Build Coastguard Worker   // processing" mode and reset streams. Returns true if so.
102*d9f75844SAndroid Build Coastguard Worker   bool MaybeResetStreamsDeferred(TSN cum_ack_tsn);
103*d9f75844SAndroid Build Coastguard Worker 
104*d9f75844SAndroid Build Coastguard Worker   // The number of payload bytes that have been queued. Note that the actual
105*d9f75844SAndroid Build Coastguard Worker   // memory usage is higher due to additional overhead of tracking received
106*d9f75844SAndroid Build Coastguard Worker   // data.
queued_bytes()107*d9f75844SAndroid Build Coastguard Worker   size_t queued_bytes() const { return queued_bytes_; }
108*d9f75844SAndroid Build Coastguard Worker 
109*d9f75844SAndroid Build Coastguard Worker   // The remaining bytes until the queue has reached the watermark limit.
remaining_bytes()110*d9f75844SAndroid Build Coastguard Worker   size_t remaining_bytes() const { return watermark_bytes_ - queued_bytes_; }
111*d9f75844SAndroid Build Coastguard Worker 
112*d9f75844SAndroid Build Coastguard Worker   // Indicates if the queue is full. Data should not be added to the queue when
113*d9f75844SAndroid Build Coastguard Worker   // it's full.
is_full()114*d9f75844SAndroid Build Coastguard Worker   bool is_full() const { return queued_bytes_ >= max_size_bytes_; }
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker   // Indicates if the queue is above the watermark limit, which is a certain
117*d9f75844SAndroid Build Coastguard Worker   // percentage of its size.
is_above_watermark()118*d9f75844SAndroid Build Coastguard Worker   bool is_above_watermark() const { return queued_bytes_ >= watermark_bytes_; }
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   // Returns the watermark limit, in bytes.
watermark_bytes()121*d9f75844SAndroid Build Coastguard Worker   size_t watermark_bytes() const { return watermark_bytes_; }
122*d9f75844SAndroid Build Coastguard Worker 
123*d9f75844SAndroid Build Coastguard Worker   HandoverReadinessStatus GetHandoverReadiness() const;
124*d9f75844SAndroid Build Coastguard Worker 
125*d9f75844SAndroid Build Coastguard Worker   void AddHandoverState(DcSctpSocketHandoverState& state);
126*d9f75844SAndroid Build Coastguard Worker   void RestoreFromState(const DcSctpSocketHandoverState& state);
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker  private:
129*d9f75844SAndroid Build Coastguard Worker   bool IsConsistent() const;
130*d9f75844SAndroid Build Coastguard Worker   void AddReassembledMessage(rtc::ArrayView<const UnwrappedTSN> tsns,
131*d9f75844SAndroid Build Coastguard Worker                              DcSctpMessage message);
132*d9f75844SAndroid Build Coastguard Worker   void MaybeMoveLastAssembledWatermarkFurther();
133*d9f75844SAndroid Build Coastguard Worker 
134*d9f75844SAndroid Build Coastguard Worker   struct DeferredResetStreams {
DeferredResetStreamsDeferredResetStreams135*d9f75844SAndroid Build Coastguard Worker     explicit DeferredResetStreams(OutgoingSSNResetRequestParameter req)
136*d9f75844SAndroid Build Coastguard Worker         : req(std::move(req)) {}
137*d9f75844SAndroid Build Coastguard Worker     OutgoingSSNResetRequestParameter req;
138*d9f75844SAndroid Build Coastguard Worker     std::vector<std::pair<TSN, Data>> deferred_chunks;
139*d9f75844SAndroid Build Coastguard Worker   };
140*d9f75844SAndroid Build Coastguard Worker 
141*d9f75844SAndroid Build Coastguard Worker   const std::string log_prefix_;
142*d9f75844SAndroid Build Coastguard Worker   const size_t max_size_bytes_;
143*d9f75844SAndroid Build Coastguard Worker   const size_t watermark_bytes_;
144*d9f75844SAndroid Build Coastguard Worker   UnwrappedTSN::Unwrapper tsn_unwrapper_;
145*d9f75844SAndroid Build Coastguard Worker 
146*d9f75844SAndroid Build Coastguard Worker   // Whenever a message has been assembled, either increase
147*d9f75844SAndroid Build Coastguard Worker   // `last_assembled_tsn_watermark_` or - if there are gaps - add the message's
148*d9f75844SAndroid Build Coastguard Worker   // TSNs into delivered_tsns_ so that messages are not re-delivered on
149*d9f75844SAndroid Build Coastguard Worker   // duplicate chunks.
150*d9f75844SAndroid Build Coastguard Worker   UnwrappedTSN last_assembled_tsn_watermark_;
151*d9f75844SAndroid Build Coastguard Worker   std::set<UnwrappedTSN> delivered_tsns_;
152*d9f75844SAndroid Build Coastguard Worker   // Messages that have been reassembled, and will be returned by
153*d9f75844SAndroid Build Coastguard Worker   // `FlushMessages`.
154*d9f75844SAndroid Build Coastguard Worker   std::vector<DcSctpMessage> reassembled_messages_;
155*d9f75844SAndroid Build Coastguard Worker 
156*d9f75844SAndroid Build Coastguard Worker   // If present, "deferred reset processing" mode is active.
157*d9f75844SAndroid Build Coastguard Worker   absl::optional<DeferredResetStreams> deferred_reset_streams_;
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker   // Contains the last request sequence number of the
160*d9f75844SAndroid Build Coastguard Worker   // OutgoingSSNResetRequestParameter that was performed.
161*d9f75844SAndroid Build Coastguard Worker   ReconfigRequestSN last_completed_reset_req_seq_nbr_;
162*d9f75844SAndroid Build Coastguard Worker 
163*d9f75844SAndroid Build Coastguard Worker   // The number of "payload bytes" that are in this queue, in total.
164*d9f75844SAndroid Build Coastguard Worker   size_t queued_bytes_ = 0;
165*d9f75844SAndroid Build Coastguard Worker 
166*d9f75844SAndroid Build Coastguard Worker   // The actual implementation of ReassemblyStreams.
167*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<ReassemblyStreams> streams_;
168*d9f75844SAndroid Build Coastguard Worker };
169*d9f75844SAndroid Build Coastguard Worker }  // namespace dcsctp
170*d9f75844SAndroid Build Coastguard Worker 
171*d9f75844SAndroid Build Coastguard Worker #endif  // NET_DCSCTP_RX_REASSEMBLY_QUEUE_H_
172