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